Biorąc pod uwagę, że został utworzony rok wcześniej niż 1103495, myślę, że to pytanie jest duplikatem tego.
MattH
2
Dzięki, Matt. Po prostu próbowałem je połączyć, nie wskazując, który z nich był pierwszy. Zobaczysz, że na drugim pytaniu mam dokładnie ten sam tekst. Czy jest lepszy sposób na powiązanie dwóch pytań?
Microsoft TextFieldParser jest stabilny i zgodny z RFC 4180 dla plików CSV. Nie zniechęcaj się Microsoft.VisualBasicprzestrzenią nazw; jest to standardowy komponent w .NET Framework, wystarczy dodać odwołanie do Microsoft.VisualBasiczestawu globalnego .
Jeśli kompilujesz dla systemu Windows (w przeciwieństwie do Mono) i nie przewidujesz konieczności analizowania „uszkodzonych” (niezgodnych z RFC) plików CSV, to byłby to oczywisty wybór, ponieważ jest darmowy, nieograniczony, stabilny, i aktywnie wspierane, o większości których nie można powiedzieć o FileHelpers.
W rzeczywistości nie ma nic specyficznego dla języka VB w tej klasie poza przestrzenią nazw o niestety nazwanej nazwie. Zdecydowanie wybrałbym tę bibliotekę, gdybym potrzebował tylko „prostego” parsera CSV, ponieważ nie ma o co pobierać, rozpowszechniać ani się o co martwić. W tym celu zredagowałem sformułowanie skoncentrowane na VB w tej odpowiedzi.
Aaronaught
@Aaronaught Myślę, że Twoje zmiany to głównie poprawa. Chociaż ten RFC niekoniecznie jest autorytatywny, ponieważ wielu autorów CSV nie przestrzega go, np. Excel nie zawsze używa przecinka w plikach „CSV”. Czy moja poprzednia odpowiedź nie mówiła już, że klasa może być używana z C #?
MarkJ
TextFieldParserPraca będzie rozdzielany tabulatorami i inne dziwne Excel generowanego cruft też. Zdaję sobie sprawę, że Twoja poprzednia odpowiedź nie wskazywała, że biblioteka jest specyficzna dla VB, po prostu przyszła mi do głowy jako sugestia, że była naprawdę przeznaczona dla VB i nie jest przeznaczona do użycia z C #, co nie wydaje mi się przypadek - w MSVB jest kilka naprawdę przydatnych klas.
Wymaga to dostępu do systemu plików. O ile wiem, nie ma sposobu, aby OLEDB działał ze strumieniami w pamięci :(
UserControl
3
@UserControl, oczywiście, wymaga dostępu do systemu plików. Zapytał o import pliku CSV
Kevin
1
Nie narzekam. W rzeczywistości wolałbym rozwiązanie OLEDB od reszty, ale byłem sfrustrowany tak wiele razy, gdy trzeba było przeanalizować CSV w aplikacjach ASP.NET, więc chciałem to zauważyć.
UserControl
12
Jeśli spodziewasz się dość złożonych scenariuszy analizowania CSV, nawet nie myśl o toczeniu naszego własnego parsera . Istnieje wiele doskonałych narzędzi, takich jak FileHelpers , a nawet te z CodeProject .
Chodzi o to, że jest to dość powszechny problem i można się założyć, że wielu programistów już przemyślało i rozwiązało ten problem.
Chociaż ten link może odpowiedzieć na pytanie, lepiej jest zawrzeć tutaj zasadnicze części odpowiedzi i podać link do odniesienia. Odpowiedzi zawierające tylko łącze mogą stać się nieprawidłowe, jeśli połączona strona ulegnie zmianie. - Z recenzji
techspider
Dzięki @techspider Mam nadzieję, że zauważyłeś, że ten post pochodzi z okresu beta StackOverflow: D To powiedziawszy, że obecnie narzędzia CSV są lepiej pozyskiwane z pakietów Nuget - więc nie jestem pewien, czy nawet odpowiedzi na linki są odporne na 8 lat -stare cykle ewolucji technologii
Jon Limjap
9
Brian daje fajne rozwiązanie do konwersji go na kolekcję silnie wpisaną.
Większość podanych metod analizy CSV nie bierze pod uwagę pól ucieczki ani niektórych innych subtelności plików CSV (takich jak pola przycinania). Oto kod, którego osobiście używam. Jest trochę szorstki na krawędziach i prawie nie ma raportowania błędów.
publicstaticIList<IList<string>>Parse(string content){IList<IList<string>> records =newList<IList<string>>();StringReader stringReader =newStringReader(content);bool inQoutedString =false;IList<string> record =newList<string>();StringBuilder fieldBuilder =newStringBuilder();while(stringReader.Peek()!=-1){char readChar =(char)stringReader.Read();if(readChar =='\n'||(readChar =='\r'&& stringReader.Peek()=='\n')){// If it's a \r\n combo consume the \n part and throw it away.if(readChar =='\r'){
stringReader.Read();}if(inQoutedString){if(readChar =='\r'){
fieldBuilder.Append('\r');}
fieldBuilder.Append('\n');}else{
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder =newStringBuilder();
records.Add(record);
record =newList<string>();
inQoutedString =false;}}elseif(fieldBuilder.Length==0&&!inQoutedString){if(char.IsWhiteSpace(readChar)){// Ignore leading whitespace}elseif(readChar =='"'){
inQoutedString =true;}elseif(readChar ==','){
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder =newStringBuilder();}else{
fieldBuilder.Append(readChar);}}elseif(readChar ==','){if(inQoutedString){
fieldBuilder.Append(',');}else{
record.Add(fieldBuilder.ToString().TrimEnd());
fieldBuilder =newStringBuilder();}}elseif(readChar =='"'){if(inQoutedString){if(stringReader.Peek()=='"'){
stringReader.Read();
fieldBuilder.Append('"');}else{
inQoutedString =false;}}else{
fieldBuilder.Append(readChar);}}else{
fieldBuilder.Append(readChar);}}
record.Add(fieldBuilder.ToString().TrimEnd());
records.Add(record);return records;}
Zauważ, że nie obsługuje to skrajnych przypadków pól, które nie są oddzielone podwójnymi cudzysłowami, ale meerley ma w sobie ciąg znaków w cudzysłowie. Zobacz ten post, aby uzyskać lepsze rozszerzenie, a także kilka linków do niektórych odpowiednich bibliotek.
Zgadzam się z @ NotMyself . FileHelpers jest dobrze przetestowany i obsługuje wszystkie rodzaje skrajnych przypadków, z którymi w końcu będziesz musiał sobie poradzić, jeśli zrobisz to sam. Spójrz na to, co robi FileHelpers i napisz własne tylko wtedy, gdy jesteś absolutnie pewien, że albo (1) nigdy nie będziesz musiał zajmować się skrajnymi przypadkami, które robi FileHelpers, albo (2) uwielbiasz pisać tego rodzaju rzeczy i zamierzasz ciesz się, gdy musisz analizować takie rzeczy:
Byłem znudzony, więc zmodyfikowałem kilka rzeczy, które napisałem. Próbuje hermetyzować parsowanie w sposób OO, jednocześnie zmniejszając liczbę iteracji w pliku, a iteruje tylko raz na początku.
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.IO;namespaceConsoleApplication1{classProgram{staticvoidMain(string[] args){// usage:// note this wont run as getting streams is not Implemented// but will get you startedCSVFileParser fileParser =newCSVFileParser();// TO Do: configure fileparserPersonParser personParser =newPersonParser(fileParser);List<Person> persons =newList<Person>();// if the file is large and there is a good way to limit// without having to reparse the whole file you can use a // linq query if you desireforeach(Person person in personParser.GetPersons()){
persons.Add(person);}// now we have a list of Person objects}}publicabstractclassCSVParser{protectedString[] deliniators ={","};protectedinternalIEnumerable<String[]>GetRecords(){Stream stream =GetStream();StreamReader reader =newStreamReader(stream);String[] aRecord;while(!reader.EndOfStream){
aRecord = reader.ReadLine().Split(deliniators,StringSplitOptions.None);yieldreturn aRecord;}}protectedabstractStreamGetStream();}publicclassCSVFileParser:CSVParser{// to do: add logic to get a stream from a fileprotectedoverrideStreamGetStream(){thrownewNotImplementedException();}}publicclassCSVWebParser:CSVParser{// to do: add logic to get a stream from a web requestprotectedoverrideStreamGetStream(){thrownewNotImplementedException();}}publicclassPerson{publicStringName{get;set;}publicStringAddress{get;set;}publicDateTime DOB {get;set;}}publicclassPersonParser{publicPersonParser(CSVParser parser){this.Parser= parser;}publicCSVParserParser{get;set;}publicIEnumerable<Person>GetPersons(){foreach(String[] record inthis.Parser.GetRecords()){yieldreturnnewPerson(){Name= record[0],Address= record[1],
DOB =DateTime.Parse(record[2]),};}}}}
Dobrym, prostym sposobem jest otwarcie pliku i wczytanie każdego wiersza do tablicy, listy połączonej, wybranej struktury danych. Uważaj jednak na pierwszą linię.
Może to być ponad twoją głową, ale wydaje się, że istnieje bezpośredni sposób na uzyskanie do nich dostępu za pomocą parametrów połączenia .
Dlaczego nie spróbować użyć Pythona zamiast C # lub VB? Ma ładny moduł CSV do zaimportowania, który wykonuje wszystkie ciężkie prace za Ciebie.
Nie skacz do Pythona z VB ze względu na parser CSV. Jest jeden w VB. Chociaż wydaje się dziwne, że zostało to zignorowane w odpowiedziach na to pytanie. msdn.microsoft.com/en-us/library/…
MarkJ
1
Tego lata musiałem użyć parsera CSV w .NET do projektu i zdecydowałem się na sterownik Microsoft Jet Text Driver. Określasz folder za pomocą parametrów połączenia, a następnie odpytuj plik za pomocą instrukcji SQL Select. Silne typy można określić za pomocą pliku schema.ini. Na początku tego nie zrobiłem, ale potem otrzymywałem złe wyniki, gdy typ danych nie był od razu widoczny, na przykład numery IP lub wpis typu „XYQ 3.9 SP1”.
Jedynym ograniczeniem, na które natknąłem się, jest to, że nie obsługuje nazw kolumn powyżej 64 znaków; to obcina. Nie powinno to stanowić problemu, poza tym, że miałem do czynienia z bardzo źle zaprojektowanymi danymi wejściowymi. Zwraca ADO.NET DataSet.
To było najlepsze rozwiązanie, jakie znalazłem. Byłbym ostrożny, jeśli chodzi o rozwijanie własnego parsera CSV, ponieważ prawdopodobnie przegapiłbym niektóre przypadki końcowe, a nie znalazłem żadnych innych bezpłatnych pakietów parsujących CSV dla .NET.
EDYCJA: Ponadto w każdym katalogu może istnieć tylko jeden plik schema.ini, więc dodałem do niego dynamicznie, aby silnie wpisać potrzebne kolumny. Będzie tylko silnie wpisywać określone kolumny i wywnioskować dla dowolnego nieokreślonego pola. Naprawdę to doceniam, ponieważ miałem do czynienia z importowaniem płynnego pliku CSV z kolumnami 70+ i nie chciałem określać każdej kolumny, tylko te źle działające.
Mogą istnieć biblioteki, których możesz użyć, aby pomóc, ale prawdopodobnie jest to tak proste, jak tylko możesz. Po prostu upewnij się, że nie możesz mieć przecinków w danych, w przeciwnym razie będziesz musiał lepiej je przeanalizować.
bardzo złe zużycie pamięci i dużo narzutów. Małe powinno być mniejsze dzięki kilku kilobajtom. Zdecydowanie nie jest to dobre dla pliku CSV o wielkości 10 MB!
Odpowiedzi:
Microsoft TextFieldParser jest stabilny i zgodny z RFC 4180 dla plików CSV. Nie zniechęcaj się
Microsoft.VisualBasic
przestrzenią nazw; jest to standardowy komponent w .NET Framework, wystarczy dodać odwołanie doMicrosoft.VisualBasic
zestawu globalnego .Jeśli kompilujesz dla systemu Windows (w przeciwieństwie do Mono) i nie przewidujesz konieczności analizowania „uszkodzonych” (niezgodnych z RFC) plików CSV, to byłby to oczywisty wybór, ponieważ jest darmowy, nieograniczony, stabilny, i aktywnie wspierane, o większości których nie można powiedzieć o FileHelpers.
Zobacz także: Porady: odczytywanie z plików tekstowych rozdzielanych przecinkami w języku Visual Basic, aby zapoznać się z przykładem kodu VB.
źródło
TextFieldParser
Praca będzie rozdzielany tabulatorami i inne dziwne Excel generowanego cruft też. Zdaję sobie sprawę, że Twoja poprzednia odpowiedź nie wskazywała, że biblioteka jest specyficzna dla VB, po prostu przyszła mi do głowy jako sugestia, że była naprawdę przeznaczona dla VB i nie jest przeznaczona do użycia z C #, co nie wydaje mi się przypadek - w MSVB jest kilka naprawdę przydatnych klas.Użyj połączenia OleDB.
źródło
Jeśli spodziewasz się dość złożonych scenariuszy analizowania CSV, nawet nie myśl o toczeniu naszego własnego parsera . Istnieje wiele doskonałych narzędzi, takich jak FileHelpers , a nawet te z CodeProject .
Chodzi o to, że jest to dość powszechny problem i można się założyć, że wielu programistów już przemyślało i rozwiązało ten problem.
źródło
Brian daje fajne rozwiązanie do konwersji go na kolekcję silnie wpisaną.
Większość podanych metod analizy CSV nie bierze pod uwagę pól ucieczki ani niektórych innych subtelności plików CSV (takich jak pola przycinania). Oto kod, którego osobiście używam. Jest trochę szorstki na krawędziach i prawie nie ma raportowania błędów.
Zauważ, że nie obsługuje to skrajnych przypadków pól, które nie są oddzielone podwójnymi cudzysłowami, ale meerley ma w sobie ciąg znaków w cudzysłowie. Zobacz ten post, aby uzyskać lepsze rozszerzenie, a także kilka linków do niektórych odpowiednich bibliotek.
źródło
Zgadzam się z @ NotMyself . FileHelpers jest dobrze przetestowany i obsługuje wszystkie rodzaje skrajnych przypadków, z którymi w końcu będziesz musiał sobie poradzić, jeśli zrobisz to sam. Spójrz na to, co robi FileHelpers i napisz własne tylko wtedy, gdy jesteś absolutnie pewien, że albo (1) nigdy nie będziesz musiał zajmować się skrajnymi przypadkami, które robi FileHelpers, albo (2) uwielbiasz pisać tego rodzaju rzeczy i zamierzasz ciesz się, gdy musisz analizować takie rzeczy:
1, „Bill”, „Smith”, „Supervisor”, „No Comment”
2, „Drake”, „O'Malley”, „Woźny,
Ups, nie jestem cytowany i jestem na nowej linii!
źródło
Byłem znudzony, więc zmodyfikowałem kilka rzeczy, które napisałem. Próbuje hermetyzować parsowanie w sposób OO, jednocześnie zmniejszając liczbę iteracji w pliku, a iteruje tylko raz na początku.
źródło
Istnieją dwa artykuły na temat CodeProject, które zawierają kod rozwiązania, jeden wykorzystujący StreamReader i jeden importujący dane CSV przy użyciu sterownika Microsoft Text Driver .
źródło
Dobrym, prostym sposobem jest otwarcie pliku i wczytanie każdego wiersza do tablicy, listy połączonej, wybranej struktury danych. Uważaj jednak na pierwszą linię.
Może to być ponad twoją głową, ale wydaje się, że istnieje bezpośredni sposób na uzyskanie do nich dostępu za pomocą parametrów połączenia .
Dlaczego nie spróbować użyć Pythona zamiast C # lub VB? Ma ładny moduł CSV do zaimportowania, który wykonuje wszystkie ciężkie prace za Ciebie.
źródło
Tego lata musiałem użyć parsera CSV w .NET do projektu i zdecydowałem się na sterownik Microsoft Jet Text Driver. Określasz folder za pomocą parametrów połączenia, a następnie odpytuj plik za pomocą instrukcji SQL Select. Silne typy można określić za pomocą pliku schema.ini. Na początku tego nie zrobiłem, ale potem otrzymywałem złe wyniki, gdy typ danych nie był od razu widoczny, na przykład numery IP lub wpis typu „XYQ 3.9 SP1”.
Jedynym ograniczeniem, na które natknąłem się, jest to, że nie obsługuje nazw kolumn powyżej 64 znaków; to obcina. Nie powinno to stanowić problemu, poza tym, że miałem do czynienia z bardzo źle zaprojektowanymi danymi wejściowymi. Zwraca ADO.NET DataSet.
To było najlepsze rozwiązanie, jakie znalazłem. Byłbym ostrożny, jeśli chodzi o rozwijanie własnego parsera CSV, ponieważ prawdopodobnie przegapiłbym niektóre przypadki końcowe, a nie znalazłem żadnych innych bezpłatnych pakietów parsujących CSV dla .NET.
EDYCJA: Ponadto w każdym katalogu może istnieć tylko jeden plik schema.ini, więc dodałem do niego dynamicznie, aby silnie wpisać potrzebne kolumny. Będzie tylko silnie wpisywać określone kolumny i wywnioskować dla dowolnego nieokreślonego pola. Naprawdę to doceniam, ponieważ miałem do czynienia z importowaniem płynnego pliku CSV z kolumnami 70+ i nie chciałem określać każdej kolumny, tylko te źle działające.
źródło
Wpisałem jakiś kod. Wynik w datagridviewer wyglądał dobrze. Przetwarza pojedynczy wiersz tekstu do tablicy obiektów.
źródło
Jeśli możesz zagwarantować, że w danych nie ma przecinków, najprostszym sposobem byłoby prawdopodobnie użycie String.split .
Na przykład:
Mogą istnieć biblioteki, których możesz użyć, aby pomóc, ale prawdopodobnie jest to tak proste, jak tylko możesz. Po prostu upewnij się, że nie możesz mieć przecinków w danych, w przeciwnym razie będziesz musiał lepiej je przeanalizować.
źródło