537 Stimmen

Umgang mit Kommas in einer CSV-Datei

Ich bin auf der Suche nach Vorschlägen, wie eine CSV-Datei zu behandeln ist, die von unseren Kunden erstellt und dann hochgeladen wird und die möglicherweise ein Komma in einem Wert enthält, z. B. einen Firmennamen.

Einige der Ideen, die wir in Betracht ziehen, sind: Bezeichner in Anführungszeichen (Wert "," Werte ", "usw.) oder die Verwendung eines | anstelle eines Kommas. Das größte Problem ist, dass wir es einfach machen müssen, sonst wird der Kunde es nicht tun.

9voto

NikolaiDante Punkte 18043

Es gibt eine Bibliothek über Nuget für den Umgang mit so ziemlich jeder gut geformten CSV (.net) - CsvHelper

Beispiel für die Zuordnung zu einer Klasse:

var csv = new CsvReader( textReader );
var records = csv.GetRecords<MyClass>();

Beispiel zum Lesen einzelner Felder:

var csv = new CsvReader( textReader );
while( csv.Read() )
{
    var intField = csv.GetField<int>( 0 );
    var stringField = csv.GetField<string>( 1 );
    var boolField = csv.GetField<bool>( "HeaderName" );
}

Das Dateiformat wird vom Kunden bestimmt:
, ist das Standardfeldbegrenzungszeichen, " ist der Standardwert, der verwendet wird, um Felder, die ein Trennzeichen, ein Anführungszeichen oder einen Zeilenabschluss enthalten, zu umgehen.

So verwenden Sie (zum Beispiel) # für Felder und ' für die Flucht:

var csv = new CsvReader( textReader );
csv.Configuration.Delimiter = "#";
csv.Configuration.Quote = ''';
// read the file however meets your needs

Mehr Dokumentation

7voto

KeyNone Punkte 8037

Für den Fall, dass Sie auf einem * sind nix-system haben Zugang zu sed und es kann eine oder mehrere unerwünschte Kommas nur in einer spezifischer Bereich Ihrer CSV-Datei, können Sie den folgenden Einzeiler verwenden, um sie in " als RFC4180 Abschnitt 2 schlägt vor:

sed -r 's/([^,]*,[^,]*,[^,]*,)(.*)(,.*,.*)/\1"\2"\3/' inputfile

Je nachdem, in welchem Feld die unerwünschten Kommata stehen, müssen Sie die Erfassungsgruppen der Regex (und die Ersetzung) ändern/erweitern.
Im obigen Beispiel wird das vierte Feld (von insgesamt sechs) in Anführungszeichen gesetzt.

enter image description here

In Kombination mit dem --in-place -Option können Sie diese Änderungen direkt auf die Datei anwenden.

Um die richtige Regex zu "bauen", gibt es ein einfaches Prinzip zu befolgen:

  1. Für jedes Feld in Ihrer CSV, das mit antes de das Feld mit dem/den unerwünschten Komma(s) schreiben Sie ein [^,]*, und fügen Sie sie alle in einer Erfassungsgruppe zusammen.
  2. Für das Feld, das das/die unerwünschte(n) Komma(s) enthält, schreiben Sie (.*) .
  3. Für jedes Feld nach das Feld mit dem/den unerwünschten Komma(s) schreiben Sie ein ,.* und fügen Sie sie alle in einer Erfassungsgruppe zusammen.

Hier ist ein kurzer Überblick über die verschiedenen möglichen Regexe/Substitutionen je nach dem spezifischen Feld. Wenn nicht angegeben, ist die Ersetzung \1"\2"\3 .

([^,]*)(,.*)                     #first field, regex
"\1"\2                           #first field, substitution

(.*,)([^,]*)                     #last field, regex
\1"\2"                           #last field, substitution

([^,]*,)(.*)(,.*,.*,.*)          #second field (out of five fields)
([^,]*,[^,]*,)(.*)(,.*)          #third field (out of four fields)
([^,]*,[^,]*,[^,]*,)(.*)(,.*,.*) #fourth field (out of six fields)

Wenn Sie das/die unerwünschte(n) Komma(s) entfernen möchten mit sed anstatt sie in Anführungszeichen zu setzen, verweisen Sie auf diese Antwort .

6voto

MikeDub Punkte 4893

Wie in meinem Kommentar zu Harpos Antwort erwähnt, ist seine Lösung gut und funktioniert in den meisten Fällen, aber in einigen Szenarien, wenn Kommas direkt nebeneinander stehen, schlägt die Trennung an den Kommas fehl.

Dies liegt daran, dass sich die Regex-Zeichenkette unerwartet wie eine Vertabim-Zeichenkette verhält. Um dieses Verhalten zu korrigieren, müssen alle "-Zeichen in der Regex-Zeichenkette manuell escaped werden, ohne die Vertabim-Escape-Funktion zu verwenden.

D.h.. Die Regex sollte diese mit manuellen Escapes sein:

",(?=(?:[^\"\"]*\"\"[^\"\"]*\"\")*(?![^\"\"]*\"\"))"

was sich wie folgt ausdrückt ",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"

Bei Verwendung einer vertabim-Zeichenkette @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))" verhält es sich wie folgt, wie Sie sehen können, wenn Sie die Regex debuggen:

",(?=(?:[^"]*"[^"]*")*(?![^"]*"))"

Zusammenfassend empfehle ich also die Lösung von harpo, aber achten Sie auf diesen kleinen Haken!

Ich habe in den CsvReader eine kleine optionale Failsafe-Funktion eingebaut, die Sie benachrichtigt, wenn dieser Fehler auftritt (wenn Sie eine vorher bekannte Anzahl von Spalten haben):

if (_expectedDataLength > 0 && values.Length != _expectedDataLength) 
throw new DataLengthException(string.Format("Expected {0} columns when splitting csv, got {1}", _expectedDataLength, values.Length));

Diese kann über den Konstruktor injiziert werden:

public CsvReader(string fileName, int expectedDataLength = 0) : this(new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
    _expectedDataLength = expectedDataLength;
}

6voto

H. Pauwelyn Punkte 12464

In Europa haben wir dieses Problem schon früher als diese Frage. In Europa verwenden wir alle ein Komma für einen Dezimalpunkt. Siehe diese Zahlen unten:

| American      | Europe        |
| ------------- | ------------- |
| 0.5           | 0,5           |
| 3.14159265359 | 3,14159265359 |
| 17.54         | 17,54         |
| 175,186.15    | 175.186,15    |

Es ist also nicht möglich, das Komma als Trennzeichen für CSV-Dateien zu verwenden. Aus diesem Grund werden die CSV-Dateien in Europa durch ein Semikolon getrennt ( ; ) .

Programme wie Microsoft Excel können Dateien mit einem Semikolon lesen, und es ist möglich, von einem Trennzeichen zu einem anderen zu wechseln. Sie können sogar einen Tabulator ( \t ) als Trennzeichen. Siehe diese Antwort von Supper User .

5voto

Rufus Pollock Punkte 2235

Sie können alternative "Trennzeichen" wie ";" oder "|" verwenden, aber am einfachsten ist es, wenn Sie einfach in Anführungszeichen setzen, was von den meisten (anständigen) CSV-Bibliotheken und den meisten anständigen Tabellenkalkulationen unterstützt wird.

Para mehr über CSV-Begrenzungszeichen und eine Spezifikation für ein Standardformat zur Beschreibung von Begrenzungszeichen und Anführungszeichen finden Sie auf dieser Webseite

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X