Benutzer mit den meisten Antworten
CSV mit TextfieldParser lesen

Frage
-
Hallo,
ich lese CSV-Dateien mit dem Microsoft.VisualBasic.FileIO.TextFieldParser ein. Bisher hat alles wunderbar funktioniert.
Nun gibt es ein Problem, wenn in einem Feld Anführungszeichen vorkommen:
23,Vorname,"Aus dem Magazin \"schön programmieren\"", Nachname
In diesem Fall wird die nachstehende Exception geworfen:
Microsoft.VisualBasic.FileIO.MalformedLineException: Die Zeile 2 kann mit den aktuellen Trennzeichen nicht analysiert werden.
bei Microsoft.VisualBasic.FileIO.TextFieldParser.ParseDelimitedLine()Ersetze ich \" mit einem Hochkomme ' gibt es keine Probleme. Habt Ihr eine Idee, wie ich solche Fälle behandeln kann?
Danke und Grüße,
Christian
Antworten
-
Hallo,
ich würde (besonders unter C#) nicht auf den VB Namespace vertrauen. Den gibt es so nur noch am Desktop und dort auch nur noch aus Kompatibilitätsgründen.Das Parsen an sich funktioniert auch über LINQ extrem einfach. Ein Beispiel dazu:
var rows = File.ReadLines("<DATEINAME>").Select(x=>x.Split('<SPLITCHAR>')).ToArray();
<SPLITCHAR> ist dabei ndas Trennzeichen der einzelnen Spalten im Datensatz.
Nun musst du nurnoch die einzelnen Zeilen und dann die jeweile Spalte per Index auswählen:
var value = rows[ZEILENINDEX][SPALTENINDEX];
PS: Wenn du alle Datensätze in einer foreach-Schleife durchlaufen willst, solltest du das ToArray am Ende der Abfrage weg lassen. Dadurch wird die Datei Zeile für Zeile gelesen, was bei großen Dateien effizienter ist.
Tom Lambert - C# MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort vorgeschlagen Aleksander Chalabashiev Mittwoch, 1. Oktober 2014 06:15
- Als Antwort markiert Tom Lambert (Koopakiller)Moderator Donnerstag, 26. März 2015 11:58
-
Hallo Christian,
ich schließe mich da Tom an. Es gibt aber falls du LINQ nicht verwenden möchtest oder kannst mind. eine weitere Möglichkeit. Du kann einen StreamReader nutzen, die Datei Zeilenweise einlesen und die Zeile nach den Feldern splitten. Der Fehler tritt dabei nicht auf und diese Methode ist um einiges schneller als per TextFieldParser.
char[] delimiters = new char[] { ',' }; using (StreamReader reader = new StreamReader("C:\\test.csv")) { while (true) { string line = reader.ReadLine(); if (line == null) { break; } string[] parts = line.Split(delimiters); Console.WriteLine("{0} field(s)", parts.Length); } }
Gruß
Jens Gerber
- Als Antwort markiert Tom Lambert (Koopakiller)Moderator Donnerstag, 26. März 2015 11:59
-
Hallo Christian,
zu dem bereits von anderen Gesagten:
Umgehen kann der TextFieldParser "nur" mit gedoppelten Anführungszeichen, so würde z. B. funktionieren:
21,Vorname,"Aus dem Magazin ""schön programmieren""", Nachname
Was ein "üblicheres" Format ist, weil es u. a. bei Textdateien von Microsoft Access (uam.) verwendet wird.
Ein Escape via Backslash wie es C# (und andere Sprachen) kennt, unterstützt er nicht - der Text-Import von Access übrigens auch nicht - insofern ist Dein CSV Format etwas zu eigen.
Gruß Elmar
- Als Antwort markiert Tom Lambert (Koopakiller)Moderator Donnerstag, 26. März 2015 11:59
Alle Antworten
-
Hallo,
ich würde (besonders unter C#) nicht auf den VB Namespace vertrauen. Den gibt es so nur noch am Desktop und dort auch nur noch aus Kompatibilitätsgründen.Das Parsen an sich funktioniert auch über LINQ extrem einfach. Ein Beispiel dazu:
var rows = File.ReadLines("<DATEINAME>").Select(x=>x.Split('<SPLITCHAR>')).ToArray();
<SPLITCHAR> ist dabei ndas Trennzeichen der einzelnen Spalten im Datensatz.
Nun musst du nurnoch die einzelnen Zeilen und dann die jeweile Spalte per Index auswählen:
var value = rows[ZEILENINDEX][SPALTENINDEX];
PS: Wenn du alle Datensätze in einer foreach-Schleife durchlaufen willst, solltest du das ToArray am Ende der Abfrage weg lassen. Dadurch wird die Datei Zeile für Zeile gelesen, was bei großen Dateien effizienter ist.
Tom Lambert - C# MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort vorgeschlagen Aleksander Chalabashiev Mittwoch, 1. Oktober 2014 06:15
- Als Antwort markiert Tom Lambert (Koopakiller)Moderator Donnerstag, 26. März 2015 11:58
-
Hallo Christian,
ich schließe mich da Tom an. Es gibt aber falls du LINQ nicht verwenden möchtest oder kannst mind. eine weitere Möglichkeit. Du kann einen StreamReader nutzen, die Datei Zeilenweise einlesen und die Zeile nach den Feldern splitten. Der Fehler tritt dabei nicht auf und diese Methode ist um einiges schneller als per TextFieldParser.
char[] delimiters = new char[] { ',' }; using (StreamReader reader = new StreamReader("C:\\test.csv")) { while (true) { string line = reader.ReadLine(); if (line == null) { break; } string[] parts = line.Split(delimiters); Console.WriteLine("{0} field(s)", parts.Length); } }
Gruß
Jens Gerber
- Als Antwort markiert Tom Lambert (Koopakiller)Moderator Donnerstag, 26. März 2015 11:59
-
Ja, in dem Fall müsstest du den String zunächst an einem anderen Zeichen aufspalten.
var rows = File.ReadAllText.Split(';').Select(x=>x.Split(',')).ToArray(); //Statt Zeilenumbruch werden Datensätze durch ';' getrennt //Datenfelder durch ','
CSV Dateien dürfen an sich weder Datensatztrennzeichen (normalerweise Zeilenumbrüche), noch Trennzeichen (oftmals Semikolons) in den Werten enthalten.
Welche Zeichen verwendet werden, macht beim parsen aber kaum einen Unterschied. Auch wenn es mit Zeilenumbrüchen am einfachsten ist.Tom Lambert - C# MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets -
Hallo Christian,
zu dem bereits von anderen Gesagten:
Umgehen kann der TextFieldParser "nur" mit gedoppelten Anführungszeichen, so würde z. B. funktionieren:
21,Vorname,"Aus dem Magazin ""schön programmieren""", Nachname
Was ein "üblicheres" Format ist, weil es u. a. bei Textdateien von Microsoft Access (uam.) verwendet wird.
Ein Escape via Backslash wie es C# (und andere Sprachen) kennt, unterstützt er nicht - der Text-Import von Access übrigens auch nicht - insofern ist Dein CSV Format etwas zu eigen.
Gruß Elmar
- Als Antwort markiert Tom Lambert (Koopakiller)Moderator Donnerstag, 26. März 2015 11:59
-
Hallo Christian,
ja hättest du. In meinem Beispiel entspricht ein Zeilenumbruch einem neuen Datensatz. In dem LINQ Beispiel von Tom scheint man das umgehen zu können (aus meiner Sicht ist das dann aber keine konsistente CSV Datei mehr). Ich würde heutzutage (außer es geht nicht anders bspw. weil es eine Schnittstelle zu einem anderen Programm ist) keine CSV Dateien für irgendwelche Exporte oder Importe nutzen. Mit XML hat man da wesentlich weniger Probleme.
Gruß
Jens Gerber