Wie man CSV spaltet, deren Spalten enthalten können,

Gegeben

2,1016,7 / 31/2008 14: 22, Geoff Dalgas, 6/5/2011 22:21, http://stackoverflow.com , “Corvallis, OR”, 7679351,81, b437f461b3fd27387c5d8ab47a293d35,34

So verwenden Sie C #, um die obigen Informationen wie folgt in Zeichenfolgen aufzuteilen:

2 1016 7/31/2008 14:22 Geoff Dalgas 6/5/2011 22:21 http://stackoverflow.com Corvallis, OR 7679 351 81 b437f461b3fd27387c5d8ab47a293d35 34 

Wie Sie sehen können, enthält eine der Spalten <= (Corvallis, OR)

// update // Basierend auf C # Regex Split – Komma außerhalb der Anführungszeichen

 string[] result = Regex.Split(samplestring, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"); 

Verwenden Sie die Microsoft.VisualBasic.FileIO.TextFieldParser class. Dies behandelt die Analyse einer Datei mit Trennzeichen, TextReader oder Stream wobei einige Felder in Anführungszeichen eingeschlossen sind und andere nicht.

Beispielsweise:

 using Microsoft.VisualBasic.FileIO; string csv = "2,1016,7/31/2008 14:22,Geoff Dalgas,6/5/2011 22:21,http://stackoverflow.com,\"Corvallis, OR\",7679,351,81,b437f461b3fd27387c5d8ab47a293d35,34"; TextFieldParser parser = new TextFieldParser(new StringReader(csv)); // You can also read from a file // TextFieldParser parser = new TextFieldParser("mycsvfile.csv"); parser.HasFieldsEnclosedInQuotes = true; parser.SetDelimiters(","); string[] fields; while (!parser.EndOfData) { fields = parser.ReadFields(); foreach (string field in fields) { Console.WriteLine(field); } } parser.Close(); 

Dies sollte zu folgender Ausgabe führen:

 2
 1016
 31.7.2008 14:22
 Geoff Dalgas
 6/5/2011 22:21
 http://stackoverflow.com
 Corvallis, ODER
 7679
 351
 81
 b437f461b3fd27387c5d8ab47a293d35
 34

Weitere Informationen finden Sie unter Microsoft.VisualBasic.FileIO.TextFieldParser .

Sie müssen einen Verweis auf Microsoft.VisualBasic auf der Registerkarte Referenzen hinzufügen .NET hinzufügen.

Sie könnten auf alle Kommas aufteilen, denen eine gerade Anzahl von Anführungszeichen folgt.

Sie möchten auch das CSV-Format zum Umgang mit Kommas im specf .

Nützlicher Link: C# Regex Split - commas outside quotes

Es ist so spät, aber das kann für jemanden hilfreich sein. Wir können RegEx wie folgt verwenden.

 Regex CSVParser = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))"); String[] Fields = CSVParser.Split(Test); 

Ich sehe, dass wenn Sie csv-Text mit Trennzeichen in Excel einfügen und einen “Text zu Spalten” machen, Sie nach einem “Text-Qualifier” gefragt werden. Es ist standardmäßig auf ein Anführungszeichen gesetzt, so dass Text in Anführungszeichen als Literal behandelt wird. Ich stelle mir vor, dass Excel dies implementiert, indem es sich jeweils um ein Zeichen bewegt. Wenn es einen “Text-Qualifier” vorfindet, geht es weiter zum nächsten “Qualifier”. Sie können dies wahrscheinlich selbst mit einer for-Schleife und einem booleschen Wert implementieren, um anzugeben, ob Sie sich in einem literalen Text befinden.

 public string[] CsvParser(string csvText) { List tokens = new List(); int last = -1; int current = 0; bool inText = false; while(current < csvText.Length) { switch(csvText[current]) { case '"': inText = !inText; break; case ',': if (!inText) { tokens.Add(csvText.Substring(last + 1, (current - last)).Trim(' ', ',')); last = current; } break; default: break; } current++; } if (last != csvText.Length - 1) { tokens.Add(csvText.Substring(last+1).Trim()); } return tokens.ToArray(); } 

Es ist eine knifflige Angelegenheit, CSV-Dateien zu analysieren, wenn die CSV-Datei entweder durch Kommas getrennte Zeichenfolgen, durch Komma getrennte Zeichenfolgen in Anführungszeichen oder eine chaotische Kombination der beiden Zeichenfolgen sein kann. Die Lösung, die ich mir ausgedacht habe, lässt eine der drei Möglichkeiten zu.

Ich habe eine Methode, ParseCsvRow () erstellt, die ein Array aus einer CSV-Zeichenfolge zurückgibt. Ich behandle zuerst doppelte Anführungszeichen in der Zeichenfolge, indem ich die Zeichenfolge in Anführungszeichen in ein Array mit dem Namen quotesArray aufspalte. Zitierte Zeichenfolge .csv-Dateien sind nur gültig, wenn eine gerade Anzahl von Anführungszeichen vorhanden ist. Doppelte Anführungszeichen in einem Spaltenwert sollten durch doppelte Anführungszeichen ersetzt werden (Dies ist der Ansatz von Excel). Solange die CSV-Datei diese Anforderungen erfüllt, können Sie erwarten, dass die Trennzeichen Kommas nur außerhalb von doppelten Anführungszeichen angezeigt werden. Kommas innerhalb von doppelten Anführungszeichen sind Teil des Spaltenwerts und sollten ignoriert werden, wenn die CSV in ein Array aufgeteilt wird.

Meine Methode testet auf Kommas außerhalb von Double-Quote-Paaren, indem nur die geraden Indizes von quotesArray betrachtet werden. Es entfernt auch doppelte Anführungszeichen vom Anfang und Ende der Spaltenwerte.

  public static string[] ParseCsvRow(string csvrow) { const string obscureCharacter = "ᖳ"; if (csvrow.Contains(obscureCharacter)) throw new Exception("Error: csv row may not contain the " + obscureCharacter + " character"); var unicodeSeparatedString = ""; var quotesArray = csvrow.Split('"'); // Split string on double quote character if (quotesArray.Length > 1) { for (var i = 0; i < quotesArray.Length; i++) { // CSV must use double quotes to represent a quote inside a quoted cell // Quotes must be paired up // Test if a comma lays outside a pair of quotes. If so, replace the comma with an obscure unicode character if (Math.Round(Math.Round((decimal) i/2)*2) == i) { var s = quotesArray[i].Trim(); switch (s) { case ",": quotesArray[i] = obscureCharacter; // Change quoted comma seperated string to quoted "obscure character" seperated string break; } } // Build string and Replace quotes where quotes were expected. unicodeSeparatedString += (i > 0 ? "\"" : "") + quotesArray[i].Trim(); } } else { // String does not have any pairs of double quotes. It should be safe to just replace the commas with the obscure character unicodeSeparatedString = csvrow.Replace(",", obscureCharacter); } var csvRowArray = unicodeSeparatedString.Split(obscureCharacter[0]); for (var i = 0; i < csvRowArray.Length; i++) { var s = csvRowArray[i].Trim(); if (s.StartsWith("\"") && s.EndsWith("\"")) { csvRowArray[i] = s.Length > 2 ? s.Substring(1, s.Length - 2) : ""; // Remove start and end quotes. } } return csvRowArray; } 

Ein Nachteil meiner Herangehensweise ist die Art und Weise, wie ich Trennzeichenkommata vorübergehend durch ein obskures Unicodezeichen ersetze. Dieser Charakter muss so dunkel sein, dass er niemals in der CSV-Datei angezeigt wird. Vielleicht möchten Sie hier mehr Abhilfe schaffen.

Verwenden Sie eine Bibliothek wie LumenWorks , um Ihre CSV-Lesung durchzuführen . Es behandelt Felder mit Anführungszeichen in ihnen und wird wahrscheinlich insgesamt robuster sein als Ihre benutzerdefinierte Lösung, da es schon seit langer Zeit existiert.

Ich hatte ein Problem mit einer CSV, die Felder mit einem Anführungszeichen in ihnen enthält, also habe ich mit dem TextFieldParser Folgendes gefunden:

 private static string[] parseCSVLine(string csvLine) { using (TextFieldParser TFP = new TextFieldParser(new MemoryStream(Encoding.UTF8.GetBytes(csvLine)))) { TFP.HasFieldsEnclosedInQuotes = true; TFP.SetDelimiters(","); try { return TFP.ReadFields(); } catch (MalformedLineException) { StringBuilder m_sbLine = new StringBuilder(); for (int i = 0; i < TFP.ErrorLine.Length; i++) { if (i > 0 && TFP.ErrorLine[i]== '"' &&(TFP.ErrorLine[i + 1] != ',' && TFP.ErrorLine[i - 1] != ',')) m_sbLine.Append("\"\""); else m_sbLine.Append(TFP.ErrorLine[i]); } return parseCSVLine(m_sbLine.ToString()); } } } 

Ein StreamReader wird weiterhin verwendet, um CSV zeilenweise wie folgt zu lesen:

 using(StreamReader SR = new StreamReader(FileName)) { while (SR.Peek() >-1) myStringArray = parseCSVLine(SR.ReadLine()); } 

Mit Cinchoo ETL – einer Open-Source-Bibliothek – können Spaltenwerte , die Trennzeichen enthalten, automatisch verarbeitet werden.

 string csv = @"2,1016,7/31/2008 14:22,Geoff Dalgas,6/5/2011 22:21,http://stackoverflow.com,""Corvallis, OR"",7679,351,81,b437f461b3fd27387c5d8ab47a293d35,34"; using (var p = ChoCSVReader.LoadText(csv) ) { Console.WriteLine(p.Dump()); } 

Ausgabe:

 Key: Column1 [Type: String] Value: 2 Key: Column2 [Type: String] Value: 1016 Key: Column3 [Type: String] Value: 7/31/2008 14:22 Key: Column4 [Type: String] Value: Geoff Dalgas Key: Column5 [Type: String] Value: 6/5/2011 22:21 Key: Column6 [Type: String] Value: http://stackoverflow.com Key: Column7 [Type: String] Value: Corvallis, OR Key: Column8 [Type: String] Value: 7679 Key: Column9 [Type: String] Value: 351 Key: Column10 [Type: String] Value: 81 Key: Column11 [Type: String] Value: b437f461b3fd27387c5d8ab47a293d35 Key: Column12 [Type: String] Value: 34 

Für weitere Informationen, besuchen Sie bitte Codeproject Artikel.

Ich hoffe es hilft.