Szukam sugestii, jak obsługiwać plik csv, który jest tworzony, a następnie przesyłany przez naszych klientów, który może mieć przecinek w wartości, na przykład nazwę firmy.
Niektóre z pomysłów, na które patrzymy, to: cytowane identyfikatory (wartość „,” wartości ”,„ itd.) Lub użycie | zamiast przecinka. Największym problemem jest to, że musimy to ułatwić, inaczej klient tego nie zrobi.
Odpowiedzi:
Jak powiedzieli inni, musisz uciec od wartości zawierających cudzysłowy. Oto mały czytnik CSV w C♯, który obsługuje wartości cytowane, w tym osadzone cytaty i zwroty karetki.
Nawiasem mówiąc, jest to kod testowany jednostkowo. Publikuję je teraz, ponieważ wydaje się, że to pytanie często pojawia się, a inni mogą nie chcieć całej biblioteki, jeśli wystarczy prosta obsługa CSV.
Możesz użyć tego w następujący sposób:
Oto zajęcia. Pamiętaj, że możesz również użyć tej
Csv.Escape
funkcji do napisania prawidłowego pliku CSV.źródło
W 2017 r. Plik csv jest w pełni określony - RFC 4180.
Jest to bardzo powszechna specyfikacja i jest całkowicie objęta wieloma bibliotekami ( przykład ).
Po prostu użyj dowolnej łatwo dostępnej biblioteki csv - to znaczy RFC 4180.
W rzeczywistości istnieje specyfikacja formatu CSV i sposobu obsługi przecinków:
http://tools.ietf.org/html/rfc4180
Tak więc, aby mieć wartości
foo
ibar,baz
robisz to:Kolejny ważny wymóg do rozważenia (również ze specyfikacji):
źródło
System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator
.Format CSV używa przecinków do oddzielenia wartości, wartości zawierające znaki powrotu karetki, linie, przecinki lub podwójne cudzysłowy są otoczone podwójnymi cudzysłowami. Wartości zawierające podwójne cudzysłowy są cytowane, a każdy dosłowny cytat jest poprzedzany cytatem bezpośrednio poprzedzającym: Na przykład 3 wartości:
byłoby zakodowane jako:
Każde pole może być cytowane, ale muszą zawierać tylko pola zawierające przecinki, CR / NL lub cudzysłowy być cytowane.
Nie ma prawdziwego standardu dla formatu CSV, ale prawie wszystkie aplikacje są zgodne z konwencjami tu udokumentowanymi . RFC, o którym wspomniano w innym miejscu, nie jest standardem dla CSV, jest RFC do używania CSV w MIME i zawiera pewne niekonwencjonalne i niepotrzebne ograniczenia, które czynią go bezużytecznym poza MIME.
Problemem, którego wiele modułów CSV nie widziało, jest fakt, że wiele linii może być zakodowanych w jednym polu, co oznacza, że nie możesz założyć, że każda linia jest osobnym rekordem, albo musisz nie zezwalać na nowe linie w swoim dane lub bądź przygotowany na to.
źródło
Umieść podwójne cudzysłowy wokół ciągów. Tak ogólnie robi Excel .
Ala Eli,
źródło
Możesz wstawiać podwójne cudzysłowy wokół pól. Nie podoba mi się to podejście, ponieważ dodaje kolejną postać specjalną (podwójny cytat). Po prostu zdefiniuj znak ucieczki (zwykle ukośnik odwrotny) i użyj go tam, gdzie potrzebujesz czegoś:
Nie musisz próbować dopasowywać cytatów i masz mniej wyjątków do analizy. Upraszcza to również kod.
źródło
W bibliotece nuget dostępna jest biblioteka do obsługi praktycznie każdego poprawnie sformatowanego pliku CSV (.net) - CsvHelper
Przykład odwzorowania na klasę:
Przykład odczytu poszczególnych pól:
Pozwalanie klientowi sterować formatem pliku:
,
jest standardowym separatorem pól,"
jest standardową wartością używaną do zmiany znaczenia pól zawierających separator, cudzysłów lub zakończenie linii.Aby użyć (na przykład)
#
do pól i'
do ucieczki:Więcej dokumentacji
źródło
CsvHelper
biblioteki do rozwiązania problemu PO.Jak wspomniano w moim komentarzu do odpowiedzi harpo, jego rozwiązanie jest dobre i działa w większości przypadków, jednak w niektórych sytuacjach, gdy przecinki jako bezpośrednio przylegające do siebie nie dzielą się na przecinki.
Wynika to z faktu, że ciąg Regex zachowuje się nieoczekiwanie jako ciąg Vertabim. Aby uzyskać prawidłowe zachowanie, wszystkie znaki w ciągu wyrażenia regularnego muszą być poprzedzane znakami ucieczki bez użycia znaku ucieczki wertykulacji.
To znaczy. Wyrażenie regularne powinno być takie przy użyciu ręcznych zmian znaczenia:
",(?=(?:[^\"\"]*\"\"[^\"\"]*\"\")*(?![^\"\"]*\"\"))"
co przekłada się na
",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
Podczas korzystania z ciągu vertabim
@",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
zachowuje się on w następujący sposób, jak widać po debugowaniu wyrażenia regularnego:Podsumowując, polecam rozwiązanie harpo, ale uważaj na tę małą gotcha!
Dołączyłem do CsvReadera trochę opcjonalnego zabezpieczenia przed awarią, aby powiadomić cię, jeśli wystąpi ten błąd (jeśli masz wcześniej znaną liczbę kolumn):
Można to zrobić za pomocą konstruktora:
źródło
[^""]
to samo co[^"]
? Powielanie znaku w specyfikacji klasy znaków jest zbędne, prawda?Dodaj odniesienie do Microsoft.VisualBasic (tak, mówi VisualBasic, ale działa również w C # - pamiętaj, że na końcu wszystko to tylko IL).
Użyj
Microsoft.VisualBasic.FileIO.TextFieldParser
klasy do parsowania pliku CSV Oto przykładowy kod:źródło
parser.HasFieldsEnclosedInQuotes = true;
a plik wejściowy musiałby zawierać pola zawierające przecinki w cudzysłowach zgodnie ze specyfikacją CSV - excel już to robi.Możesz użyć alternatywnych „ograniczników”, takich jak „;” lub „|” ale najprostszym może być cytowanie, które jest obsługiwane przez większość (przyzwoitych) bibliotek CSV i najbardziej przyzwoitych arkuszy kalkulacyjnych.
Więcej informacji na temat ograniczników CSV i specyfikacji standardowego formatu opisywania ograniczników i cytowania można znaleźć na tej stronie internetowej
źródło
W przypadku, gdy jesteś na * nix-system , mieć dostęp do
sed
i tam może być jeden lub więcej tylko w niechciane przecinki dziedzinie określonej w pliku CSV, można użyć następującego jedno-liner, aby dołączyć je"
jako RFC4180 Sekcji 2 proponuje:W zależności od tego, w którym polu mogą znajdować się niechciane przecinki, musisz zmienić / rozszerzyć grupy przechwytywania wyrażenia regularnego (i podstawienie).
Powyższy przykład umieści czwarte pole (spośród sześciu) w cudzysłowie.
W połączeniu z
--in-place
opcją można zastosować te zmiany bezpośrednio do pliku.Aby „zbudować” właściwe wyrażenie regularne, należy przestrzegać prostej zasady:
[^,]*,
i umieszczasz je wszystkie w grupie przechwytywania.(.*)
.,.*
i umieszczasz je wszystkie w grupie przechwytywania.Oto krótki przegląd różnych możliwych wyrażeń regularnych / podstawień w zależności od konkretnego pola. Jeśli nie podano, podstawienie to
\1"\2"\3
.Jeśli chcesz usunąć niechciane przecinki,
sed
zamiast umieszczać je w cudzysłowie, zapoznaj się z tą odpowiedzią .źródło
Jeśli masz ochotę wymyślić koło na nowo, mogą Ci pomóc następujące rzeczy:
źródło
W Europie mamy ten problem wcześniej niż to pytanie. W Europie używamy przecinka do przecinka dziesiętnego. Zobacz te liczby poniżej:
Dlatego nie można użyć separatora przecinków dla plików CSV. Z tego powodu pliki CSV w Europie są oddzielone średnikiem (
;
) .Programy takie jak Microsoft Excel mogą odczytywać pliki średnikiem i można przełączyć się z separatora. Możesz nawet użyć tab (
\t
) jako separatora. Zobacz tę odpowiedź od użytkownika wieczerzy .źródło
Jeśli interesuje Cię bardziej edukacyjne zadanie dotyczące ogólnej analizy plików (na przykład CSV), możesz przeczytać ten artykuł autorstwa Juliana Bucknalla. Podoba mi się ten artykuł, ponieważ dzieli on rzeczy na znacznie mniejsze problemy, które są znacznie mniej nie do pokonania. Najpierw tworzysz gramatykę, a kiedy masz dobrą gramatykę, jest to stosunkowo łatwy i metodyczny proces konwersji gramatyki na kod.
Artykuł używa C # i ma link na dole, aby pobrać kod.
źródło
Oto schludne małe obejście:
Zamiast tego możesz użyć greckiego dolnego znaku liczbowego (U + 0375)
Tak to wygląda ͵
Korzystanie z tej metody oszczędza również wiele zasobów ...
źródło
Wystarczy użyć SoftCircuits.CsvParser na NuGet. Obsługuje wszystkie te szczegóły i skutecznie obsługuje bardzo duże pliki. W razie potrzeby może nawet importować / eksportować obiekty poprzez mapowanie kolumn na właściwości obiektu. Ponadto moje testy wykazały, że jest to średnio 4 razy szybsze niż popularny CsvHelper.
źródło
Ponieważ chodzi o ogólne praktyki, zacznijmy od podstawowych zasad:
Nie używaj CSV, zamiast tego używaj XML z biblioteką do odczytu i zapisu pliku xml.
Jeśli musisz użyć CSV. Zrób to poprawnie i użyj darmowej biblioteki do parsowania i przechowywania plików CSV.
Aby uzasadnić 1), większość parserów CSV nie jest świadoma kodowania, więc jeśli nie masz do czynienia z US-ASCII, pytasz o problemy. Na przykład excel 2002 przechowuje CSV w lokalnym kodowaniu bez żadnej uwagi na temat kodowania. Standard CSV nie jest powszechnie przyjęty :(. Z drugiej strony standard xml jest dobrze przyjęty i całkiem dobrze obsługuje kodowanie.
Aby uzasadnić 2), istnieje mnóstwo parserów csv dla prawie wszystkich języków, więc nie ma potrzeby wymyślania nowego koła, nawet jeśli rozwiązania wyglądają dość prosto.
Aby wymienić tylko kilka:
dla Pythona użyj wbudowanego modułu csv
dla Perla sprawdź CPAN i Text :: CSV
dla php użyj wbudowanej funkcji fgetcsv / fputcsv
dla java sprawdź bibliotekę SuperCVS
Naprawdę nie ma potrzeby implementowania tego ręcznie, jeśli nie zamierzasz go analizować na urządzeniu osadzonym.
źródło
Możesz odczytać plik csv w ten sposób.
wykorzystuje podział i dba o przestrzeń.
źródło
Najpierw zadajmy sobie pytanie: „Dlaczego czujemy potrzebę innego traktowania przecinków dla plików CSV?”
Dla mnie odpowiedź brzmi: „Ponieważ kiedy eksportuję dane do pliku CSV, przecinki w polu znikają, a moje pole zostaje podzielone na wiele pól, w których przecinki pojawiają się w oryginalnych danych”. (To dlatego, że przecinek jest znakiem separatora pól CSV).
W zależności od sytuacji średniki mogą być również używane jako separatory pól CSV.
Biorąc pod uwagę moje wymagania, mogę użyć znaku, np. Pojedynczego niskiego 9 cudzysłowu, który wygląda jak przecinek.
Oto, jak możesz to zrobić w Go:
Drugi znak przecinka w funkcji zamiany to dziesiętny 8218.
Należy pamiętać, że jeśli masz klientów, którzy mogą mieć czytniki tekstu tylko ascii, ten znak decima 8218 nie będzie wyglądał jak przecinek. Jeśli tak jest w twoim przypadku, polecam otaczanie pola przecinkiem (lub średnikiem) z podwójnymi cudzysłowami zgodnie z RFC 4128: https://tools.ietf.org/html/rfc4180
źródło
Zazwyczaj koduję adresy URL pól, które mogą zawierać przecinki lub znaki specjalne. A następnie dekoduj go, gdy jest używany / wyświetlany na dowolnym nośniku wizualnym.
(przecinki stają się% 2C)
Każdy język powinien mieć metody kodowania i dekodowania ciągów adresów URL.
np. w java
Wiem, że jest to bardzo ogólne rozwiązanie i może nie być idealne w sytuacji, gdy użytkownik chce ręcznie przeglądać zawartość pliku csv.
źródło
Zwykle robię to w procedurach analizy plików CSV. Załóżmy, że zmienna „linia” jest jedną linią w pliku CSV, a wszystkie wartości kolumn są ujęte w podwójne cudzysłowy. Po wykonaniu dwóch poniższych wierszy otrzymasz kolumny CSV w kolekcji „wartości”.
źródło
Najprostszym rozwiązaniem, jakie znalazłem, jest to, którego używa LibreOffice:
"
na”
Możesz także użyć tego, którego używa Excel:
"
na""
Zwróć uwagę, że innym osobom zaleca się wykonanie tylko kroku 2 powyżej, ale to nie działa z wierszami, po których
"
następuje a,
, np. W CSV, w którym chcesz mieć pojedynczą kolumnę z ciągiemhello",world
, tak jak CSV:Który jest interpretowany jako wiersz z dwiema kolumnami:
hello
iworld"
źródło
hello",world
pole musiałoby po prostu zostać zapisane jako"hello"",world"
, które można poprawnie przeanalizować w 100%.źródło
Użyłem biblioteki Csvreader, ale używając tego, dostałem dane, eksplodując z przecinka (,) w wartości kolumny.
Więc jeśli chcesz wstawić dane pliku CSV, które zawierają przecinek (,) w większości wartości kolumn, możesz użyć funkcji poniżej. Link do autora => https://gist.github.com/jaywilliams/385876
źródło
Użyłem biblioteki papaParse do przeanalizowania pliku CSV i uzyskania par klucz-wartość (klucz / nagłówek / pierwszy wiersz wartości pliku CSV).
oto przykład, którego używam:
https://codesandbox.io/embed/llqmrp96pm
ma tam plik dummy.csv, aby mieć wersję demonstracyjną CSV.
Użyłem go w ReagJS, chociaż można go łatwo replikować w aplikacji napisanej w dowolnym języku.
źródło
Przykład może pomóc pokazać, jak przecinki mogą być wyświetlane w pliku .csv. Utwórz prosty plik tekstowy w następujący sposób:
Zapisz ten plik tekstowy jako plik tekstowy z przyrostkiem „.csv” i otwórz go w programie Excel 2000 z systemu Windows 10.
aa, bb, cc, d; d "W prezentacji arkusza kalkulacyjnego dolna linia powinna wyglądać jak powyższa linia, z tym wyjątkiem, że poniżej pokazuje wyświetlany przecinek zamiast średnika między literami d." aa, bb, cc, „d, d”, Działa to nawet w programie Excel
aa, bb, cc, „d, d”, Działa to nawet w programie Excel 2000 aa, bb, cc, „d, d”, Działa to nawet w programie Excel 2000 aa, bb, cc, „d, d”, Działa nawet w programie Excel 2000
aa, bb, cc, „d, d”, To się nie udaje w programie Excel 2000 z powodu miejsca poniżej 1. cytatu aa, bb, cc, „d, d”, To kończy się niepowodzeniem w programie Excel 2000 z powodu miejsca poniżej 1. cytatu aa, bb, cc, „d, d”, Nie udaje się to w programie Excel 2000 z powodu spacji poniżej 1. cytatu
aa, bb, cc, „d, d”, Działa to nawet w programie Excel 2000, nawet ze spacjami przed drugim cytatem i po nim. aa, bb, cc, „d, d”, Działa to nawet w programie Excel 2000, nawet ze spacjami przed drugim cytatem i po nim. aa, bb, cc, „d, d”, Działa to nawet w programie Excel 2000, nawet ze spacjami przed drugim cytatem i po nim.
Reguła: Jeśli chcesz wyświetlać przecinek w komórce (polu) pliku .csv: „Rozpocznij i zakończ pole podwójnymi cudzysłowami, ale unikaj spacji przed pierwszym cytatem”
źródło
Myślę, że najłatwiejszym rozwiązaniem tego problemu jest otwarcie klienta csv w programie Excel, a następnie naciśnięcie klawiszy Ctrl + R, aby zastąpić wszystkie przecinki dowolnym identyfikatorem. Jest to bardzo łatwe dla klienta i wymaga tylko jednej zmiany w kodzie, aby odczytać wybrany przez siebie ogranicznik.
źródło
Użyj znaku tabulacji (\ t), aby oddzielić pola.
źródło