Umgang mit Kommas in einer CSV-Datei

472

Ich suche nach Vorschlägen für den Umgang mit einer CSV-Datei, die erstellt und dann von unseren Kunden hochgeladen wird und die möglicherweise ein Komma in einem Wert wie einem Firmennamen enthält.

Einige der Ideen, die wir betrachten, sind: zitierte Bezeichner (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.

Bob der Hausmeister
quelle
Der Kunde schreibt es und lädt es hoch
Bob The Janitor
1
Hier ist die Lösung zum Verwalten von Commos in CSV-Dateien. Besuchen Sie stackoverflow.com/questions/9889225/…
Hasan Abrar
Unter iOS müssen Sie im Wesentlichen github.com/Flinesoft/CSVImporter
Fattie
3
Beachten Sie, dass diese Qualitätssicherung alt ist. Heutzutage bedeutet CSV RFC 4180 und das war's.
Fattie
Ich habe genau das gleiche Problem und versuche, eine Spalte in einer CSV-Datei zu summieren, die durch Kommas getrennt ist. Kein Problem mit einem awk-Befehl. Leider können einige Zellen Kommas enthalten (z. B. in einer Adresse), andere nicht. Sie suchen nach einer Linux-kompatiblen Lösung, sind sich aber nicht sicher, wo Sie anfangen sollen.
Greenage

Antworten:

223

Wie andere bereits gesagt haben, müssen Sie Werte mit Anführungszeichen umgehen. Hier ist ein kleiner CSV-Reader in C♯, der Anführungszeichen unterstützt, einschließlich eingebetteter Anführungszeichen und Zeilenumbrüche.

Dies ist übrigens ein Unit-getesteter Code. Ich poste es jetzt, weil diese Frage häufig auftaucht und andere möglicherweise nicht die gesamte Bibliothek wünschen, wenn eine einfache CSV-Unterstützung ausreicht.

Sie können es wie folgt verwenden:

using System;
public class test
{
    public static void Main()
    {
        using ( CsvReader reader = new CsvReader( "data.csv" ) )
        {
            foreach( string[] values in reader.RowEnumerator )
            {
                Console.WriteLine( "Row {0} has {1} values.", reader.RowIndex, values.Length );
            }
        }
        Console.ReadLine();
    }
}

Hier sind die Klassen. Beachten Sie, dass Sie die Csv.EscapeFunktion auch zum Schreiben einer gültigen CSV verwenden können.

using System.IO;
using System.Text.RegularExpressions;

public sealed class CsvReader : System.IDisposable
{
    public CsvReader( string fileName ) : this( new FileStream( fileName, FileMode.Open, FileAccess.Read ) )
    {
    }

    public CsvReader( Stream stream )
    {
        __reader = new StreamReader( stream );
    }

    public System.Collections.IEnumerable RowEnumerator
    {
        get {
            if ( null == __reader )
                throw new System.ApplicationException( "I can't start reading without CSV input." );

            __rowno = 0;
            string sLine;
            string sNextLine;

            while ( null != ( sLine = __reader.ReadLine() ) )
            {
                while ( rexRunOnLine.IsMatch( sLine ) && null != ( sNextLine = __reader.ReadLine() ) )
                    sLine += "\n" + sNextLine;

                __rowno++;
                string[] values = rexCsvSplitter.Split( sLine );

                for ( int i = 0; i < values.Length; i++ )
                    values[i] = Csv.Unescape( values[i] );

                yield return values;
            }

            __reader.Close();
        }
    }

    public long RowIndex { get { return __rowno; } }

    public void Dispose()
    {
        if ( null != __reader ) __reader.Dispose();
    }

    //============================================


    private long __rowno = 0;
    private TextReader __reader;
    private static Regex rexCsvSplitter = new Regex( @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))" );
    private static Regex rexRunOnLine = new Regex( @"^[^""]*(?:""[^""]*""[^""]*)*""[^""]*$" );
}

public static class Csv
{
    public static string Escape( string s )
    {
        if ( s.Contains( QUOTE ) )
            s = s.Replace( QUOTE, ESCAPED_QUOTE );

        if ( s.IndexOfAny( CHARACTERS_THAT_MUST_BE_QUOTED ) > -1 )
            s = QUOTE + s + QUOTE;

        return s;
    }

    public static string Unescape( string s )
    {
        if ( s.StartsWith( QUOTE ) && s.EndsWith( QUOTE ) )
        {
            s = s.Substring( 1, s.Length - 2 );

            if ( s.Contains( ESCAPED_QUOTE ) )
                s = s.Replace( ESCAPED_QUOTE, QUOTE );
        }

        return s;
    }


    private const string QUOTE = "\"";
    private const string ESCAPED_QUOTE = "\"\"";
    private static char[] CHARACTERS_THAT_MUST_BE_QUOTED = { ',', '"', '\n' };
}
Harpo
quelle
2
Abhängig von Ihrer Anwendung müssen Sie möglicherweise auch \ r \ n übersetzen, um die Windows-Konformität zu gewährleisten.
Mandrake
3
@NadaNaeem, möchten Sie näher darauf eingehen?
Harpo
Es zählt die Elemente in einer CSV-Dateizeile nicht richtig, es geht nicht gut mit den Kommas in Feldern um und Mut kehrt zurück und tippt
Nada N. Hantouli
-1 OP gibt keine Sprache an, in der die Datei erstellt wird. Wenn ein anderer Programmierer hierher kommt und nach einer Lösung in einer anderen Sprache als C # sucht, findet er keine Lösung, die er in dieser Antwort verwenden kann.
Ben Leggiero
8
@ BenC.R.Leggiero, dann müssen Sie wohl auch die Frage ablehnen, da sie nach Ihrem Standard nicht zu beantworten ist. Der Code stellt eine formale Implementierung einer einfachen Spezifikation dar und kann problemlos in jede häufig verwendete Sprache übersetzt werden.
Harpo
395

Für 2017 ist csv vollständig spezifiziert - RFC 4180.

Es ist eine sehr verbreitete Spezifikation und wird von vielen Bibliotheken vollständig abgedeckt ( Beispiel ).

Verwenden Sie einfach eine leicht verfügbare CSV-Bibliothek - also RFC 4180.


Es gibt tatsächlich eine Spezifikation für das CSV-Format und den Umgang mit Kommas:

Felder mit Zeilenumbrüchen (CRLF), doppelten Anführungszeichen und Kommas sollten in doppelte Anführungszeichen gesetzt werden.

http://tools.ietf.org/html/rfc4180

Um Werte zu haben foound bar,bazdies zu tun, tun Sie Folgendes:

foo,"bar,baz"

Eine weitere wichtige Anforderung, die berücksichtigt werden muss (auch aus der Spezifikation):

Wenn zum Einschließen von Feldern doppelte Anführungszeichen verwendet werden, muss ein doppeltes Anführungszeichen in einem Feld maskiert werden, indem ein weiteres doppeltes Anführungszeichen vorangestellt wird. Zum Beispiel:

"aaa","b""bb","ccc"
Corey Trager
quelle
120
"Felder mit Zeilenumbrüchen (CRLF), doppelten Anführungszeichen und Kommas sollten in doppelte Anführungszeichen gesetzt werden."
Eli
42
"Wenn doppelte Anführungszeichen verwendet werden, um Felder einzuschließen, muss ein doppeltes Anführungszeichen in einem Feld maskiert werden, indem ein weiteres doppeltes Anführungszeichen vorangestellt wird."
C. Dragon 76
11
Nicht wirklich eine Spezifikation, aber wahrscheinlich immer noch praktisch. Es heißt ... "Es gibt keine formale Spezifikation, die eine Vielzahl von Interpretationen von CSV-Dateien ermöglicht. Dieser Abschnitt dokumentiert das Format, dem die meisten Implementierungen zu folgen scheinen."
Justin Clarke
5
Vergessen Sie auch nicht, dass CSV-Werte in der Zeile trotz ihres Namens nicht nur durch Kommas getrennt werden können - zumindest auf Windows-Plattformen. Dies hängt von den aktuellen regionalen Einstellungen (intl.cpl in der Befehlszeile, "Erweiterte Einstellungen") ab, insbesondere vom Listentrennzeichen : System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator.
lxa
4
Bitte fügen Sie in diese Antwort zusätzlich zum Link relevante Informationen ein: A) Entfernen Sie die meisten der oben genannten Kommentare (und meine). B) Sparen Sie so viel mehr Personen als dem Antwortenden die Zeit, auf eine weitere Seite zu gehen und die relevanten zu finden Daten, C) Link Rot verhindern.
user66001
76

Das CSV-Format verwendet Kommas, um Werte zu trennen. Werte, die Zeilenumbrüche, Zeilenvorschübe, Kommas oder doppelte Anführungszeichen enthalten, sind von doppelten Anführungszeichen umgeben. Werte, die doppelte Anführungszeichen enthalten, werden in Anführungszeichen gesetzt und jedes Literal-Anführungszeichen wird durch ein unmittelbar vorhergehendes Anführungszeichen maskiert: Zum Beispiel die 3 Werte:

test
list, of, items
"go" he said

würde codiert werden als:

test
"list, of, items"
"""go"" he said"

Jedes Feld kann in Anführungszeichen gesetzt werden, aber nur Felder, die Kommas, CR / NL oder Anführungszeichen enthalten, müssen in Anführungszeichen gesetzt werden.

Es gibt keinen wirklichen Standard für das CSV-Format, aber fast alle Anwendungen folgen den hier dokumentierten Konventionen . Der an anderer Stelle erwähnte RFC ist kein Standard für CSV, sondern ein RFC für die Verwendung von CSV in MIME und enthält einige unkonventionelle und unnötige Einschränkungen, die ihn außerhalb von MIME unbrauchbar machen.

Ein Problem, das viele CSV-Module, die ich gesehen habe, nicht berücksichtigen, ist die Tatsache, dass mehrere Zeilen in einem einzigen Feld codiert werden können. Dies bedeutet, dass Sie nicht davon ausgehen können, dass jede Zeile ein separater Datensatz ist. Sie müssen entweder keine Zeilenumbrüche in Ihrem zulassen Daten oder darauf vorbereitet sein.

Robert Gamble
quelle
40

Setzen Sie doppelte Anführungszeichen um Zeichenfolgen. Das macht Excel im Allgemeinen .

Ala Eli,

Sie entkommen einem doppelten Anführungszeichen als zwei doppelte Anführungszeichen. ZB "test1", "foo", "bar", "test2"

Joe Phillips
quelle
im Grunde das gleiche Konzept wie ein zitierter Identifikator
Bob The Janitor
1
Sie entkommen einem doppelten Anführungszeichen als zwei doppelte Anführungszeichen. ZB "test1", "foo" "bar", "test2"
Eli
Nur doppelte Anführungszeichen um die Zeichenfolge zu setzen, funktioniert nicht, wenn auf ein "sofort ein Komma
folgt
9

Sie können die Felder in doppelte Anführungszeichen setzen. Ich mag diesen Ansatz nicht, da er ein weiteres Sonderzeichen hinzufügt (das doppelte Anführungszeichen). Definieren Sie einfach ein Escape-Zeichen (normalerweise Backslash) und verwenden Sie es überall dort, wo Sie etwas entkommen müssen:

Daten, mehr Daten, mehr Daten, sogar noch mehr

Sie müssen nicht versuchen, Anführungszeichen abzugleichen, und Sie müssen weniger Ausnahmen analysieren. Dies vereinfacht auch Ihren Code.

Adam Jaskiewicz
quelle
3
Schnell und schmutzig, funktioniert aber nicht, wenn Sie tatsächlich einen Eintrag haben, der "\" enthält
Sarp Kaya
1
Sarp, deshalb ist ein Double \\ ein entkommener Backslash, da dies nun zu einem weiteren Sonderzeichen wird.
Grungondola
1
Dies funktioniert, ist aber keine CSV. Es ist ein DSV .
TRiG
8

Über nuget steht eine Bibliothek zur Verfügung, die sich mit so ziemlich jedem wohlgeformten CSV (.net) - CsvHelper befasst

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" );
}

Lassen Sie den Client das Dateiformat steuern:
, ist das Standardfeldtrennzeichen, "der Standardwert, der zum Escapezeichen von Feldern verwendet wird, die ein Trennzeichen, ein Anführungszeichen oder ein Zeilenende enthalten.

So verwenden Sie (zum Beispiel) #Felder und 'Escapezeichen:

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

Weitere Dokumentation

NikolaiDante
quelle
3
Es wäre vorzuziehen, wenn Sie ein Beispiel für die Verwendung der CsvHelperBibliothek zur Lösung des OP-Problems angeben würden.
George Stocker
Warum muss fast alles in .Net ein "Helfer" sein ... das Wort ist nahezu bedeutungslos ... wie "Manager".
Bytedev
5

Wie in meinem Kommentar zu Harpos Antwort erwähnt, ist seine Lösung gut und funktioniert in den meisten Fällen. In einigen Szenarien, in denen Kommas direkt nebeneinander liegen, werden die Kommas jedoch nicht aufgeteilt.

Dies liegt daran, dass sich die Regex-Zeichenfolge unerwartet als Vertabim-Zeichenfolge verhält. Damit sich dieses Verhalten korrekt verhält, müssen alle "Zeichen in der Regex-Zeichenfolge manuell maskiert werden, ohne das Vertabim-Escape zu verwenden.

Dh. Die Regex sollte dies sein, indem manuelle Escapezeichen verwendet werden:

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

was übersetzt in ",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"

Wenn Sie eine Vertabim-Zeichenfolge verwenden @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))", verhält sie sich wie folgt: Sie können sehen, ob Sie den regulären Ausdruck debuggen:

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

Zusammenfassend kann ich die Lösung von harpo empfehlen, aber achten Sie auf dieses kleine Problem!

Ich habe eine kleine optionale Ausfallsicherheit in den CsvReader aufgenommen, um Sie zu benachrichtigen, wenn dieser Fehler auftritt (wenn Sie eine zuvor 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));

Dies kann über den Konstruktor injiziert werden:

public CsvReader(string fileName, int expectedDataLength = 0) : this(new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
    _expectedDataLength = expectedDataLength;
}
MikeDub
quelle
Wie würden Sie mit der Kopfzeile umgehen? Ich versuche, die CSV C # -Objekten zuzuordnen, die alle Typen sind, aber die Kopfzeile
unterbricht
Ist das nicht [^""]dasselbe wie [^"]? Das Duplizieren eines Zeichens innerhalb einer Zeichenklassenspezifikation ist überflüssig, oder?
Minh Tran
4

Fügen Sie einen Verweis auf Microsoft.VisualBasic hinzu (ja, dort steht VisualBasic, aber es funktioniert genauso gut in C # - denken Sie daran, dass am Ende alles nur IL ist).

Verwenden Sie die Microsoft.VisualBasic.FileIO.TextFieldParserKlasse, um die CSV-Datei zu analysieren. Hier ist der Beispielcode:

 Dim parser As TextFieldParser = New TextFieldParser("C:\mar0112.csv")
 parser.TextFieldType = FieldType.Delimited
 parser.SetDelimiters(",")      

   While Not parser.EndOfData         
      'Processing row             
      Dim fields() As String = parser.ReadFields         
      For Each field As String In fields             
         'TODO: Process field                   

      Next      
      parser.Close()
   End While 
mvilaskumar
quelle
Ja, dies ist eine sehr nützliche Klasse in einem etwas unglücklichen Namespace ;-). Um die ursprüngliche Frage zu beantworten, sollten Sie jedoch auch Einstellungen vornehmen, parser.HasFieldsEnclosedInQuotes = true;und die Eingabedatei müsste Felder, die Kommas in Anführungszeichen enthalten, gemäß der CSV-Spezifikation einschließen - Excel tut dies bereits.
Christopher King
4

Wenn Sie sich auf einem * nix-System befinden , Zugriff auf sedein oder mehrere unerwünschte Kommas nur in einem bestimmten Feld Ihrer CSV haben und diese vorhanden sein können , können Sie den folgenden Einzeiler verwenden, um sie "als RFC4180-Abschnitt einzuschließen 2 schlägt vor:

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

Abhängig davon, in welchem ​​Feld sich die unerwünschten Kommas befinden, müssen Sie die Erfassungsgruppen des regulären Ausdrucks (und der Ersetzung) ändern / erweitern.
Im obigen Beispiel wird das vierte Feld (von sechs) in Anführungszeichen gesetzt.

Geben Sie hier die Bildbeschreibung ein

In Kombination mit der --in-placeOption -option können Sie diese Änderungen direkt auf die Datei anwenden.

Um den richtigen regulären Ausdruck zu "bauen", gibt es ein einfaches Prinzip:

  1. Für jedes Feld in Ihrer CSV, das vor dem Feld mit den unerwünschten Kommas steht, schreiben Sie eines [^,]*,und fügen sie alle in einer Erfassungsgruppe zusammen.
  2. Für das Feld, das die unerwünschten Kommas enthält, die Sie schreiben (.*) .
  3. Für jedes Feld nach dem Feld mit den unerwünschten Kommas schreiben Sie eines ,.* und fügen sie alle zu einer Erfassungsgruppe zusammen.

Hier finden Sie eine kurze Übersicht über verschiedene mögliche Regexe / Substitutionen je nach Fachgebiet. Wenn nicht angegeben, ist die Substitution \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 unerwünschte Kommas entfernen möchten, sedanstatt sie in Anführungszeichen zu setzen, lesen Sie diese Antwort .

Basti M.
quelle
3

Wenn Sie das Rad neu erfinden möchten, kann Folgendes für Sie funktionieren:

public static IEnumerable<string> SplitCSV(string line)
{
    var s = new StringBuilder();
    bool escaped = false, inQuotes = false;
    foreach (char c in line)
    {
        if (c == ',' && !inQuotes)
        {
            yield return s.ToString();
            s.Clear();
        }
        else if (c == '\\' && !escaped)
        {
            escaped = true;
        }
        else if (c == '"' && !escaped)
        {
            inQuotes = !inQuotes;
        }
        else
        {
            escaped = false;
            s.Append(c);
        }
    }
    yield return s.ToString();
}
Neil
quelle
3

In Europa müssen wir dieses Problem früher als diese Frage haben. In Europa verwenden wir alle ein Komma als 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    |

Daher ist es nicht möglich, das Komma-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 vom Trennzeichen wechseln. Sie können sogar ein tab ( \t) als Trennzeichen verwenden. Siehe diese Antwort vom Supper User .

H. Pauwelyn
quelle
2

Wenn Sie an einer ausführlicheren Übung zum Parsen von Dateien im Allgemeinen interessiert sind (am Beispiel von CSV), können Sie diesen Artikel lesen von Julian Bucknall lesen. Ich mag den Artikel, weil er die Dinge in viel kleinere Probleme aufteilt, die viel weniger unüberwindbar sind. Sie erstellen zuerst eine Grammatik, und sobald Sie eine gute Grammatik haben, ist es ein relativ einfacher und methodischer Prozess, die Grammatik in Code umzuwandeln.

Der Artikel verwendet C # und hat unten einen Link zum Herunterladen des Codes.

Phil
quelle
1

Hier ist eine nette kleine Problemumgehung:

Sie können stattdessen ein griechisches Zeichen für die untere Zahl verwenden (U + 0375).

Es sieht so aus ͵

Mit dieser Methode sparen Sie auch viele Ressourcen ...

Konstantine Nikka-Sher Piterma
quelle
1

Verwenden Sie einfach SoftCircuits.CsvParser auf NuGet. Es behandelt all diese Details für Sie und verarbeitet sehr große Dateien effizient. Bei Bedarf können sogar Objekte importiert / exportiert werden, indem Spalten Objekteigenschaften zugeordnet werden. Außerdem haben meine Tests gezeigt, dass es im Durchschnitt fast viermal schneller ist als der beliebte CsvHelper.

Jonathan Wood
quelle
0

Da es sich um allgemeine Praktiken handelt, gehen wir von den Faustregeln aus:

  1. Verwenden Sie keine CSV-Datei, sondern XML mit einer Bibliothek, um stattdessen die XML-Datei zu lesen und zu schreiben.

  2. Wenn Sie CSV verwenden müssen. Machen Sie es richtig und verwenden Sie eine kostenlose Bibliothek, um die CSV-Dateien zu analysieren und zu speichern.

Um 1) zu rechtfertigen, sind die meisten CSV-Parser nicht codierungsbewusst. Wenn Sie also nicht mit US-ASCII arbeiten, fragen Sie nach Problemen. Zum Beispiel speichert Excel 2002 die CSV in lokaler Codierung ohne Hinweis auf die Codierung. Der CSV-Standard ist nicht weit verbreitet :(. Andererseits ist der XML-Standard gut übernommen und handhabt Codierungen ziemlich gut.

Um 2) zu rechtfertigen: Es gibt Unmengen von CSV-Parsern für fast alle Sprachen, sodass das Rad nicht neu erfunden werden muss, selbst wenn die Lösungen recht einfach aussehen.

Um nur einige zu nennen:

  • Verwenden Sie für Python das eingebaute CSV- Modul

  • Überprüfen Sie für Perl CPAN und Text :: CSV

  • Für PHP verwenden Sie eingebaute fgetcsv / fputcsv Funktionen

  • Für Java überprüfen Sie die SuperCVS- Bibliothek

Es ist wirklich nicht erforderlich, dies von Hand zu implementieren, wenn Sie es nicht auf einem eingebetteten Gerät analysieren möchten.

Piotr Czapla
quelle
12
XML ist nicht immer die Antwort. CSV ist das richtige Format für den Job, wenn Sie viele dichte, tabellarische Daten haben (z. B. eine Tabelle). Diese Tags verursachen viel Aufwand, und wenn jede Zeile ein identisches Format hat, muss nicht explizit angegeben werden, was jeder einzelne Wert darstellt. XML eignet sich hervorragend, wenn Sie komplizierte hierarchische Daten oder Datensätze mit optionalen Feldern haben. Das ist nicht immer der Fall.
Adam Jaskiewicz
Theoretisch verursachen die "Tags" ein wenig Overhead, aber ich kann mir keine reale Anwendung vorstellen, bei der es anfängt, ein Problem zu sein. Haben Sie praktische Beispiele? Um an Daten zu arbeiten, sollte man eine Datenbank anstelle von CSV verwenden. Wenn wir über Datenserialisierung (Backups, Datenaustausch) sprechen, spielt es dann eine Rolle, ob das Parsen eine Woche statt 5 Tage dauert?
Piotr Czapla
2
Grundsätzlich jede Situation, in der Sie Daten haben, die am besten durch eine Tabelle dargestellt werden. Angenommen, Sie haben Daten von einem Dutzend verschiedener Sensoren, die Sie von Zeit zu Zeit abtasten, und Sie zeichnen den Zeitstempel und den Wert jedes einzelnen Sensors zu diesem Zeitpunkt auf. Jeder Datensatz ist identisch: Zeitstempel, Sensor0, Sensor1, ... Sensor11. XML eignet sich hervorragend zur Darstellung komplexer, unregelmäßiger Daten, ist jedoch ein ziemlich schweres Format, das nicht für jede einzelne Situation geeignet ist. KISS
Adam Jaskiewicz
10
Einige Leute sehen ein Problem und sagen: "Ich weiß, ich werde XML verwenden!" Jetzt haben sie zwei Probleme.
Adam Jaskiewicz
Ich stimme voll und ganz zu, dass XML nicht für alles eine Antwort ist. Insbesondere eignet es sich weder als Datenbankersatz noch für Konfigurationsdateien. Hier ging es jedoch um den Datenaustausch, für den XML entwickelt wurde.
Piotr Czapla
0

Sie können die CSV-Datei so lesen.

Dies nutzt Splits und kümmert sich um Räume.

ArrayList List = new ArrayList();
static ServerSocket Server;
static Socket socket;
static ArrayList<Object> list = new ArrayList<Object>();


public static void ReadFromXcel() throws FileNotFoundException
{   
    File f = new File("Book.csv");
    Scanner in = new Scanner(f);
    int count  =0;
    String[] date;
    String[] name;
    String[] Temp = new String[10];
    String[] Temp2 = new String[10];
    String[] numbers;
    ArrayList<String[]> List = new ArrayList<String[]>();
    HashMap m = new HashMap();

         in.nextLine();
         date = in.nextLine().split(",");
         name = in.nextLine().split(",");
         numbers = in.nextLine().split(",");
         while(in.hasNext())
         {
             String[] one = in.nextLine().split(",");
             List.add(one);
         }
         int xount = 0;
         //Making sure the lines don't start with a blank
         for(int y = 0; y<= date.length-1; y++)
         {
             if(!date[y].equals(""))
             {   
                 Temp[xount] = date[y];
                 Temp2[xount] = name[y];
                 xount++;
             }
         }

         date = Temp;
         name =Temp2;
         int counter = 0;
         while(counter < List.size())
         {
             String[] list = List.get(counter);
             String sNo = list[0];
             String Surname = list[1];
             String Name = list[2];
             for(int x = 3; x < list.length; x++)
             {           
                 m.put(numbers[x], list[x]);
             }
            Object newOne = new newOne(sNo, Name, Surname, m, false);
             StudentList.add(s);
             System.out.println(s.sNo);
             counter++;
         }
Eric
quelle
0

Fragen wir uns zunächst: "Warum müssen wir Kommas für CSV-Dateien anders behandeln?"

Für mich lautet die Antwort: "Wenn ich Daten in eine CSV-Datei exportiere, verschwinden die Kommas in einem Feld und mein Feld wird in mehrere Felder aufgeteilt, in denen die Kommas in den Originaldaten erscheinen." (Das liegt daran, dass das Komma das CSV-Feldtrennzeichen ist.)

Abhängig von Ihrer Situation können Semikolons auch als CSV-Feldtrennzeichen verwendet werden.

Aufgrund meiner Anforderungen kann ich ein Zeichen verwenden, z. B. ein einzelnes Anführungszeichen mit niedriger 9, das wie ein Komma aussieht.

So können Sie es in Go machen:

// Replace special CSV characters with single low-9 quotation mark
func Scrub(a interface{}) string {
    s := fmt.Sprint(a)
    s = strings.Replace(s, ",", "‚", -1)
    s = strings.Replace(s, ";", "‚", -1)
    return s
}

Das zweite Komma in der Ersetzungsfunktion ist die Dezimalzahl 8218.

Beachten Sie, dass dieses Dezima 8218-Zeichen nicht wie ein Komma aussieht, wenn Sie Clients haben, die möglicherweise nur ASCII-Textleser haben. Wenn dies der Fall ist, würde ich empfehlen, das Feld mit einem Komma (oder Semikolon) in doppelten Anführungszeichen gemäß RFC 4128 zu umgeben: https://tools.ietf.org/html/rfc4180

l3x
quelle
0

Im Allgemeinen codiere ich die Felder, die Kommas oder Sonderzeichen enthalten können, per URL. Und dekodieren Sie es dann, wenn es in einem beliebigen visuellen Medium verwendet / angezeigt wird.

(Kommas werden zu% 2C)

Jede Sprache sollte Methoden zum URL-Codieren und Decodieren von Zeichenfolgen haben.

zB in Java

URLEncoder.encode(myString,"UTF-8"); //to encode
URLDecoder.decode(myEncodedstring, "UTF-8"); //to decode

Ich weiß, dass dies eine sehr allgemeine Lösung ist und möglicherweise nicht ideal für Situationen ist, in denen Benutzer den Inhalt von CSV-Dateien manuell anzeigen möchten.

hariszhr
quelle
0

Normalerweise mache ich das in meinen CSV-Dateien, die Routinen analysieren. Angenommen, die Variable 'line' ist eine Zeile in einer CSV-Datei und alle Werte der Spalten sind in doppelte Anführungszeichen eingeschlossen. Nachdem die folgenden zwei Zeilen ausgeführt wurden, erhalten Sie CSV-Spalten in der Auflistung 'values'.

// The below two lines will split the columns as well as trim the DBOULE QUOTES around values but NOT within them
    string trimmedLine = line.Trim(new char[] { '\"' });
    List<string> values = trimmedLine.Split(new string[] { "\",\"" }, StringSplitOptions.None).ToList();
user1451111
quelle
1
Warum wird mein Code in StackOverflow nie in mehreren Farben angezeigt? Ich rücke um vier Leerzeichen ein.
user1451111
0

Die einfachste Lösung, die ich gefunden habe, ist die, die LibreOffice verwendet:

  1. Ersetzen Sie alle Literale "durch
  2. Setzen Sie doppelte Anführungszeichen um Ihre Zeichenfolge

Sie können auch die von Excel verwendete verwenden:

  1. Ersetzen Sie alle Literale "durch""
  2. Setzen Sie doppelte Anführungszeichen um Ihre Zeichenfolge

Beachten Sie, dass andere Personen empfohlen haben, nur Schritt 2 oben auszuführen. Dies funktioniert jedoch nicht mit Zeilen, in denen a "von a gefolgt wird ,, wie in einer CSV, in der Sie eine einzelne Spalte mit der Zeichenfolge haben möchten hello",world, wie die CSV lauten würde:

"hello",world"

Welches als eine Zeile mit zwei Spalten interpretiert wird: helloundworld"

MondKin
quelle
1
Gemäß den Standardregeln ist jedes Feld, das entweder das geteilte Zeichen oder das Anführungszeichen enthält, von Anführungszeichen umgeben, und alle darin enthaltenen Anführungszeichen sind verdoppelt, sodass kein Problem vorliegt. Ihr hello",worldFeld müsste einfach als gespeichert werden "hello"",world", was zu 100% korrekt analysiert werden kann.
Nyerguds
0
    public static IEnumerable<string> LineSplitter(this string line, char 
         separator, char skip = '"')
    {
        var fieldStart = 0;
        for (var i = 0; i < line.Length; i++)
        {
            if (line[i] == separator)
            {
                yield return line.Substring(fieldStart, i - fieldStart);
                fieldStart = i + 1;
            }
            else if (i == line.Length - 1)
            {
                yield return line.Substring(fieldStart, i - fieldStart + 1);
                fieldStart = i + 1;
            }

            if (line[i] == '"')
                for (i++; i < line.Length && line[i] != skip; i++) { }
        }

        if (line[line.Length - 1] == separator)
        {
            yield return string.Empty;
        }
    }
Rajat26
quelle
0

Ich habe die Csvreader-Bibliothek verwendet, aber dadurch habe ich Daten erhalten, indem ich durch Komma (,) im Spaltenwert explodiert bin.

Wenn Sie also CSV-Dateidaten einfügen möchten, die in den meisten Spaltenwerten Komma (,) enthalten, können Sie die folgende Funktion verwenden. Autorenlink => https://gist.github.com/jaywilliams/385876

function csv_to_array($filename='', $delimiter=',')
{
    if(!file_exists($filename) || !is_readable($filename))
        return FALSE;

    $header = NULL;
    $data = array();
    if (($handle = fopen($filename, 'r')) !== FALSE)
    {
        while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE)
        {
            if(!$header)
                $header = $row;
            else
                $data[] = array_combine($header, $row);
        }
        fclose($handle);
    }
    return $data;
}
Vir
quelle
0

Ich habe die papaParse-Bibliothek verwendet, um die CSV-Datei zu analysieren und die Schlüssel-Wert-Paare (Schlüssel / Header / erste Zeile des CSV-Datei-Werts) zu haben.

Hier ist ein Beispiel, das ich benutze:

https://codesandbox.io/embed/llqmrp96pm

Es enthält die Datei dummy.csv, um die CSV-Parsing-Demo zu erhalten.

Ich habe es in reactJS verwendet, obwohl es einfach und unkompliziert in einer App zu replizieren ist, die mit einer beliebigen Sprache geschrieben wurde.

Parag Patel
quelle
0

Ein Beispiel könnte zeigen, wie Kommas in einer CSV-Datei angezeigt werden können. Erstellen Sie eine einfache Textdatei wie folgt:

Speichern Sie diese Textdatei als Textdatei mit dem Suffix ".csv" und öffnen Sie sie mit Excel 2000 unter Windows 10.

aa, bb, cc, d; d "In der Tabellenkalkulation sollte die folgende Zeile wie die obige Zeile aussehen, außer dass die folgende Zeile ein angezeigtes Komma anstelle eines Semikolons zwischen den ds zeigt." aa, bb, cc, "d, d", Dies funktioniert sogar in Excel

aa, bb, cc, "d, d", Dies funktioniert sogar in Excel 2000 aa, bb, cc, "d, d", Dies funktioniert sogar in Excel 2000 aa, bb, cc, "d, d", Dies funktioniert sogar in Excel 2000

aa, bb, cc, "d, d", Dies schlägt in Excel 2000 aufgrund des Leerzeichens vor dem ersten Anführungszeichen fehl. aa, bb, cc, "d, d". Dies schlägt in Excel 2000 aufgrund des Leerzeichens vor dem ersten Anführungszeichen fehl aa, bb, cc, "d, d". Dies schlägt in Excel 2000 aufgrund des Leerzeichens vor dem ersten Anführungszeichen fehl

aa, bb, cc, "d, d", Dies funktioniert auch in Excel 2000 auch mit Leerzeichen vor und nach dem 2. Anführungszeichen. aa, bb, cc, "d, d", Dies funktioniert auch in Excel 2000 auch mit Leerzeichen vor und nach dem 2. Anführungszeichen. aa, bb, cc, "d, d", Dies funktioniert auch in Excel 2000 auch mit Leerzeichen vor und nach dem 2. Anführungszeichen.

Regel: Wenn Sie ein Komma in einer Zelle (Feld) einer CSV-Datei anzeigen möchten: "Beginnen und beenden Sie das Feld mit doppelten Anführungszeichen, aber vermeiden Sie Leerzeichen vor dem ersten Anführungszeichen."

user1247591
quelle
-1

Ich denke, die einfachste Lösung für dieses Problem besteht darin, dass der Kunde die CSV in Excel öffnet und dann Strg + R, um alle Kommas durch die gewünschte Kennung zu ersetzen. Dies ist für den Kunden sehr einfach und erfordert nur eine Änderung Ihres Codes, um das Trennzeichen Ihrer Wahl zu lesen.

jamesdeath123
quelle
Wer sagt, dass sie Excel haben? In der Tat, wer sagt, dass es sogar ein Mensch ist, der das Hochladen macht? ...
bytedev
-3

Verwenden Sie ein Tabulatorzeichen (\ t), um die Felder zu trennen.

Pierre
quelle
4
-1 Großartig, bis jemand einen Tab in seinem Wert verwendet, dann kehren Sie direkt zu dem Problem zurück, das die Person, die die Frage stellt, hat. Das Austauschen eines Trennzeichens gegen ein anderes wird das Problem nicht lösen.
Bytedev
Unsinn. Personen können in ihrer Dateneingabe keine Registerkarten eingeben. In den meisten Formularen wird der Dateneingabepunkt einfach zum nächsten Feld verschoben.
Pierre
6
"Leute können keine Tabs in ihre Dateneingabe eingeben" .... meinst du das ernst? A) Natürlich könnte eine Person eine Registerkarte in ein Eingabefeld einfügen. B) Wer sagt, dass es sich um eine GUI handelt, von der die Daten stammen? C) Wer sagt, dass es sogar ein Mensch ist, der die Daten eingibt?
Bytedev