2009-04-17 4 views
20

Ich muss CSV und TSV-Dateien analysieren können. Ich kann mich nicht darauf verlassen, dass die Benutzer den Unterschied kennen, daher möchte ich vermeiden, dass der Benutzer den Typ auswählt. Gibt es eine einfache Möglichkeit zu erkennen, welches Trennzeichen verwendet wird?Wie soll ich feststellen, welches Trennzeichen in einer Textdatei verwendet wird?

Eine Möglichkeit wäre, in jeder Zeile zu lesen und sowohl Tabs als auch Kommas zu zählen und herauszufinden, welches in jeder Zeile am konsequentesten verwendet wird. Natürlich könnten die Daten Kommas oder Tabulatoren enthalten, so dass dies leichter gesagt als getan werden kann.

Bearbeiten: Ein weiterer Spaß Aspekt dieses Projekts ist, dass ich auch das Schema der Datei erkennen muss, wenn ich es einlese, weil es einer von vielen sein könnte. Das bedeutet, dass ich nicht weiß, wie viele Felder ich habe, bis ich es analysieren kann.

Antwort

14

Sie können die Ergebnisse im Vorschaufenster anzeigen - ähnlich wie Excel es tut. Es ist ziemlich klar, wenn in diesem Fall das falsche Trennzeichen verwendet wird. Sie können dann zulassen, dass sie einen Bereich von Begrenzern auswählen und die Vorschau in Echtzeit aktualisieren können.

Dann könnten Sie einfach eine einfache Schätzung über das Trennzeichen machen (z. B. kommt zuerst ein Komma oder ein Tab).

+2

Den Benutzer das Ergebnis vor dem Import zu zeigen, ist ein guter Zug, denke ich, aber raten intelligent ist auch großartig für userexperience. Die Kombination ist also wirklich nett! – BerggreenDK

+0

ein Vorschlag: Wenn Sie ein Vorschaufenster erstellen und "raten" möchten, welches der richtige Begrenzer ist, können Sie auf ein mögliches Trennzeichen aufteilen. und sehen Sie, ob die ersten zehn Zeilen alle die gleiche Anzahl von Feldern haben, vergleichen Sie sie mit allen anderen normalen Feldern. Es ist eine gute Wette, dass man mit der gleichen Anzahl von Feldern arbeitet. Wie [Jon Skeet sagte] (https://stackoverflow.com/questions/761932/how-should-i-detect-which-delimiter-is-used-in-a-text-file/761949#761949) ist es durchaus möglich Es ist ein gültiges kommasepariertes UND-Tab-Trennzeichen, aber dieses Tab war die beabsichtigte Wahl. – PsychoData

4

Wissen Sie, wie viele Felder sollte pro Zeile vorhanden sein? Wenn ja, würde ich die ersten Zeilen der Datei lesen und darauf basierend prüfen.

Meiner Erfahrung nach enthalten "normale" Daten häufig Kommas, aber selten Tab-Zeichen. Dies würde bedeuten, dass Sie in den ersten paar Zeilen nach einer konsistenten Anzahl von Tabs suchen sollten und diese Wahl als bevorzugte Schätzung verwenden sollten. Natürlich hängt es genau davon ab, welche Daten Sie haben.

Letztlich wäre es durchaus möglich, eine Datei zu haben, die für beide Formate vollständig gültig ist - so kann man es nicht absolut narrensicher machen. Es muss ein "Best-Effort" Job sein.

1

Es gibt keinen "effizienten" Weg.

2

Ich würde mir vorstellen, dass Ihre vorgeschlagene Lösung der beste Weg zu gehen wäre. In einer wohlgeformten CSV- oder TSV-Datei sollte die Anzahl der Kommas bzw. Tabulatoren pro Zeile konstant sein (keine Variation). Zählen Sie jeden für jede Zeile der Datei und prüfen Sie, welcher für alle Zeilen konstant ist. Es erscheint ziemlich unwahrscheinlich, dass die Anzahl der beiden Delimeter für jede Linie identisch ist, aber in diesem unvorstellbar seltenen Fall könnten Sie natürlich den Benutzer auffordern.

Wenn weder die Anzahl der Registerkarten noch die Kommas konstant ist, zeigen Sie dem Benutzer eine Meldung an, die besagt, dass die Datei fehlerhaft ist, aber das Programm denkt, dass es eine Datei mit der geringsten Standardabweichung ist .

1

Unter der Annahme, dass es eine feste Anzahl von Feldern pro Zeile gibt und dass Kommata oder Tabulatoren in Werten durch Anführungszeichen (") eingeschlossen sind, sollten Sie in der Lage sein, die Häufigkeit jedes Zeichens in jeder Zeile zu berechnen die Felder sind nicht festgelegt, das ist schwieriger, und wenn Anführungszeichen nicht verwendet werden, um ansonsten begrenzende Zeichen einzuschließen, wird es, wie ich vermute, nahezu unmöglich sein (und abhängig von den Daten länderspezifisch).

1

In Meine Erfahrung, Daten enthalten Tabs selten, so würde eine Linie von Tab-abgegrenzten Felder (im Allgemeinen) ziemlich offensichtlich sein.

Kommas sind schwieriger, obwohl - vor allem, wenn Sie Daten in nicht-US-Locales lesen. Numerische Daten ca n enthalten eine große Anzahl von Kommas, wenn Sie außerhalb des Landes erzeugte Dateien lesen, da Gleitkommazahlen diese oft enthalten.

Am Ende ist die einzige sichere Sache, jedoch, in der Regel zu versuchen, dann präsentieren Sie es dem Benutzer und erlauben Sie ihnen, anzupassen, vor allem, wenn Ihre Daten Kommas und/oder Tabs enthalten.

1

Ich würde davon ausgehen, dass im normalen Text Tabs sehr selten sind, außer als die ersten Zeichen in einer Zeile - denken Sie an eingerückten Absätzen oder Quellcode. Ich denke, wenn Sie eingebettete Registerkarten finden (d. H. Solche, die Kommata nicht folgen), können Sie davon ausgehen, dass die Registerkarten als Trennzeichen verwendet werden und die meiste Zeit korrekt sind. Dies ist nur eine Vermutung, nicht mit irgendwelchen Nachforschungen verifiziert. Ich würde natürlich dem Benutzer die Option geben, den automatisch berechneten Modus zu übersteuern.

2

Lesen Sie nur ein paar Zeilen, zählen Sie die Anzahl der Kommas und die Anzahl der Registerkarten und vergleichen Sie sie. Wenn es 20 Kommas und keine Tabs gibt, ist es in CSV. Wenn es 20 Tabs und 2 Kommas gibt (vielleicht in den Daten), ist es in TSV.

1

Angenommen, Sie einen Standardsatz von Spalten haben Sie erwarten, gehen ...

Ich würde FileHelper (Open-Source-Projekt auf Source) verwenden. http://filehelpers.sourceforge.net/

Definieren Sie zwei Leservorlagen, eine für comas, eine für Registerkarten.

Wenn die erste fehlschlägt, versuchen Sie die zweite.

+0

Das ist interessant. Ich werde in mehreren Schemas lesen und versuchen herauszufinden, welches Schema die aktuelle Datei auf dem Dateilayout basiert (Anzahl der Felder, Feldreihenfolge usw.). Kann der FileHelper feststellen, welche Klasse zur Laufzeit verwendet werden soll? – samiz

14

In Python gibt es eine Sniffer-Klasse im csv-Modul, die verwendet werden kann, um die Trennzeichen und Anführungszeichen einer bestimmten Datei zu erraten. Die Strategie wird (von csv.py der Docstrings zitiert):


[Zuerst schauen] für Text eingeschlossen zwischen zwei identischen Anführungszeichen (die wahrscheinlich QuoteChar), die vorangehen und folgten mit dem gleichen Zeichen (die wahrscheinlich Trennzeichen). Zum Beispiel:

  ,'some text', 

Das Zitat mit den meisten Siegen, das gleiche mit dem Begrenzer. Wenn kein quitchchar vorhanden ist, kann das Trennzeichen auf diese Weise nicht bestimmt werden.

In diesem Fall versuchen Sie folgendes:

Der Begrenzer sollte die gleiche Anzahl von Zeiten auf jede Zeile auftreten. Aufgrund von fehlerhaften Daten kann dies jedoch nicht der Fall sein. Wir wollen nicht einen Alles oder Nichts-Ansatz, so dass wir kleine Abweichungen in dieser Nummer zulassen.

  1. Erstellen Sie eine Tabelle mit der Häufigkeit jedes Zeichen in jeder Zeile.
  2. eine Tabelle mit Frequenzen dieser Frequenz (Meta-Frequenz?), Z. 'x aufgetreten 5 mal in 10 Reihen, 6 mal in 1000 Zeilen, 7 mal in 2 Reihen'
  3. verwenden, um den Modus der meta-Frequenz die erwarteten Frequenz für dieses Zeichen
  4. um zu bestimmen, herauszufinden, wie oft der Charakter trifft tatsächlich dieses Ziel
  5. das Zeichen, das beste seiner Ziel

Für performan ist das Trennzeichen trifft ce Gründen, die Daten werden in Chunks ausgewertet, so kann es versuchen und den kleinsten Teil der Daten möglich bewerten, zusätzliche Chunks nach Bedarf auswerten.


Ich werde hier nicht den Quellcode zitieren - es ist im Lib-Verzeichnis jeder Python-Installation.

Denken Sie daran, dass CSV auch (weil Kommas verwendet werden als Dezimaltrennzeichen in Deutschland ... sind zB in der deutschen Versionen von Excel, CSV-Dateien Semikolon getrennte)

3

Es ist in PHP Semikolons statt Kommas als Trennzeichen verwenden können, aber dies scheint recht zuverlässig zu sein:

$csv = 'something;something;something 
someotherthing;someotherthing;someotherthing 
'; 
$candidates = array(',', ';', "\t"); 
$csvlines = explode("\n", $csv); 
foreach ($candidates as $candidatekey => $candidate) { 
$lastcnt = 0; 
foreach ($csvlines as $csvline) { 
    if (strlen($csvline) <= 2) continue; 
    $thiscnt = substr_count($csvline, $candidate); 
    if (($thiscnt == 0) || ($thiscnt != $lastcnt) && ($lastcnt != 0)) { 
    unset($candidates[$candidatekey]); 
    break; 
    } 
    $lastcnt = $thiscnt; 
} 
} 
$delim = array_shift($candidates); 
echo $delim; 

Was sie tut, ist die folgende: Für jeden angegebenen möglich Begrenzer, liest jede Zeile in der CSV und prüft, ob die Anzahl der einzelnen seperator konstant auftritt, ist. Wenn nicht, wird der Kandidat Seperator entfernt und schließlich sollten Sie mit einem Separator enden.

0

können Sie überprüfen, ob eine Zeile ein Trennzeichen oder eine andere wie diese verwendet:

while ((line = readFile.ReadLine()) != null) 
{ 
    if (line.Split('\t').Length > line.Split(',').Length) // tab delimited or comma delimited? 
     row = line.Split('\t'); 
    else 
     row = line.Split(','); 

    parsedData.Add(row); 
} 
+3

Was ist, wenn es tabulatorgetrennt ist mit einem Komma in den Daten oder umgekehrt? Dies könnte möglicherweise versuchen, die gleiche Datei in tabulatorgetrennten oder kommagetrennten Formaten basierend auf den Daten in den Zeilen zu analysieren. – samiz

2

Ich lief in ein ähnliches Bedürfnis und dachte, ich würde teilen, was ich mit aufkam. Ich habe noch nicht viele Daten durchgespielt, also gibt es möglicherweise Randfälle. Beachten Sie auch, dass das Ziel dieser Funktion nicht 100% ige Sicherheit für das Trennzeichen ist, sondern dass es dem Benutzer am besten vorgestellt wird.

Verwandte Themen