2009-10-28 8 views
25

Ich verarbeite eine Zeichenfolge, die tabulatorgetrennt ist. Ich beende dies mit der split Funktion, und es funktioniert in den meisten Situationen. Das Problem tritt auf, wenn ein Feld fehlt. Anstatt also in diesem Feld null zu erhalten, erhalte ich den nächsten Wert. Ich speichere die analysierten Werte in einem String-Array.String Parsing in Java mit Delimeter Registerkarte " t" mit Split

String[] columnDetail = new String[11]; 
columnDetail = column.split("\t"); 

Jede Hilfe wäre willkommen. Wenn möglich, möchte ich die analysierten Strings in einem String-Array speichern, damit ich leicht auf die analysierten Daten zugreifen kann.

+0

So 'field1 \ tfield2 \ t \ tfield4' ergibt FIELD1 Sie, field2, field4 statt Feld1, Feld2, [null], field4? –

+3

http://stackoverflow.com/questions/1630092/token-parsing-in-java/1630110 duplizieren? Dies passiert, wenn Sie die Antworten NICHT verstehen und nur den Code kopieren. –

+2

Sie müssen kein neues String-Array zuweisen. 'String.split' weist trotzdem eine neue zu. – Joey

Antwort

78

String.split verwendet Regular Expressions, auch müssen Sie kein zusätzliches Array für Ihren Split zuweisen.

Die Split-Methode gibt Ihnen eine Liste., das Problem ist, dass Sie versuchen, vordefinieren, wie viele Vorkommen Sie von einem Tab haben, aber wie würden Sie das wirklich wissen? Probieren Sie den Scanner oder den StringTokenizer und erfahren Sie, wie Splitting-Strings funktionieren.

Lassen Sie mich erklären, warum \ t nicht funktioniert und warum Sie \\\\ benötigen, um \\ zu entkommen.

Okay, also, wenn Sie Split verwenden, nimmt es tatsächlich eine Regex (Regulärer Ausdruck) und im regulären Ausdruck möchten Sie definieren, welche Zeichen zu teilen, und wenn Sie \ t schreiben, was eigentlich nicht bedeutet \t und was willst du teilen nach ist \t, richtig? Also, indem Sie einfach \t schreiben, sagen Sie Ihrem Regex-Prozessor, dass "Hey geteilt durch den Buchstaben, der t entkommen ist" NICHT "Hey geteilt durch alle Charaktere, die wie \t aussehen". Beachten Sie den Unterschied? Mit \ bedeutet, etwas zu entkommen. Und \ in Regex bedeutet etwas völlig anders als was Sie denken.

Das ist also, warum Sie diese Lösung verwenden müssen:

\\t 

die Regex Prozessor zu sagen für \ t zu suchen. Okay, also warum brauchst du zwei davon? Nun, die erste \ entkommt der zweiten, was bedeutet, dass es so aussehen wird: \ t, wenn Sie den Text verarbeiten!

Lassen Sie uns jetzt sagen, dass Sie \

zu spalten suchen Na, dann würden Sie bleiben \\ aber sehen, das funktioniert nicht! weil \ versuchen wird, dem vorherigen Zeichen zu entkommen! Deshalb möchten Sie, dass die Ausgabe \\ ist und Sie daher \\ \\ haben müssen.

Ich hoffe wirklich, dass die obigen Beispiele Ihnen helfen zu verstehen, warum Ihre Lösung nicht funktioniert und wie Sie andere erobern!

Jetzt habe ich Ihnen diese answer vor, vielleicht sollten Sie beginnen, sie jetzt zu betrachten.

ANDERE METHODEN

StringTokenizer

Sie in die StringTokenizer aussehen sollte, ist es ein sehr nützliches Werkzeug für diese Art von Arbeit.

Beispiel

StringTokenizer st = new StringTokenizer("this is a test"); 
while (st.hasMoreTokens()) { 
    System.out.println(st.nextToken()); 
} 

Dies wird Ausgang

this 
is 
a 
test 

Sie die zweite Konstruktor für StringTokenizer verwenden das Trennzeichen zu setzen:

StringTokenizer(String str, String delim)

Scanner

Sie auch eine Scanner als einer der Kommentatoren verwenden könnte sagen dies wie diese

Beispiel

String input = "1 fish 2 fish red fish blue fish"; 

Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*"); 

System.out.println(s.nextInt()); 
System.out.println(s.nextInt()); 
System.out.println(s.next()); 
System.out.println(s.next()); 

s.close(); 

Der Ausgang

wäre etwas aussehen könnte
1 
2 
red 
blue 

Bedeutet, dass es das Wort "Fisch" ausschneiden wird und Ihnen den Rest geben wird "Fisch" als Trennzeichen.

examples taken from the Java API

+0

@Filip: nette eins! –

+2

Reguläre Ausdrücke sollten Sie jedoch nicht bei der Aufteilung auf Tab beißen. – Joey

+1

Wahrscheinlich nicht, aber wenn der OP nur versuchen würde, Antworten zu lesen und sie zu verstehen, würde er bereits die Antwort darauf wissen. Denn das ist vergleichbar mit dem, was er gestern gepostet hat. Ich würde sagen, wenn er meine Methode gestern und heute benutzt hätte, hätte er dieses Problem nicht bekommen. –

4

String.split Implementierungen werden gravierende Einschränkungen, wenn die Daten in tabulatorbegrenzter Feld selbst Newline enthält, Tab und möglicherweise "Zeichen.

TAB-getrennte Formate rund um die Jahre für Esel gewesen, aber Das Format ist nicht standardisiert und variiert. Bei vielen Implementierungen werden Zeichen (Zeilenumbrüche und Tabulatoren) nicht in einem Feld angezeigt, sondern sie folgen CSV-Konventionen und umbrechen nicht-triviale Felder in doppelte Anführungszeichen So könnte eine "Linie" sich über mehrere Linien erstrecken.

Um mich zu lesen hörte ich "nur Apache-Tools wiederverwenden", was wie ein guter Ratschlag klingt.

Am Ende wählte ich persönlich opencsv. Ich fand es leicht, und da es Optionen für Escape- und Anführungszeichen bietet, sollte es die gängigsten komma- und tabulatorgetrennten Datenformate abdecken.

Beispiel:

CSVReader tabFormatReader = new CSVReader(new FileReader("yourfile.tsv"), '\t'); 
15

Try this:

String[] columnDetail = column.split("\t", -1); 

Lesen Sie die Javadoc auf String.split(java.lang.String, int) für eine Erklärung über die Grenze Parameter der Split-Funktion:

split 

public String[] split(String regex, int limit) 
Splits this string around matches of the given regular expression. 
The array returned by this method contains each substring of this string that is terminated by another substring that matches the given expression or is terminated by the end of the string. The substrings in the array are in the order in which they occur in this string. If the expression does not match any part of the input then the resulting array has just one element, namely this string. 

The limit parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array. If the limit n is greater than zero then the pattern will be applied at most n - 1 times, the array's length will be no greater than n, and the array's last entry will contain all input beyond the last matched delimiter. If n is non-positive then the pattern will be applied as many times as possible and the array can have any length. If n is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing empty strings will be discarded. 

The string "boo:and:foo", for example, yields the following results with these parameters: 

Regex Limit Result 
: 2 { "boo", "and:foo" } 
: 5 { "boo", "and", "foo" } 
: -2 { "boo", "and", "foo" } 
o 5 { "b", "", ":and:f", "", "" } 
o -2 { "b", "", ":and:f", "", "" } 
o 0 { "b", "", ":and:f" } 

Wenn die letzten Felder (ich Gast, das ist deine Situation) fehlen, erhalten Sie die Spalte wie folgt:

field1\tfield2\tfield3\t\t 

Wenn keine Begrenzung() aufgeteilt wird, ist die Grenze 0, was zu, dass „Hinter leere Strings werden verworfen“ führen wird. Sie können also nur drei Felder erhalten, {"field1", "field2", "field3"}.

Wenn Limit auf -1 gesetzt ist, wird ein nicht positiver Wert, nachgestellte leere Zeichenfolgen, nicht verworfen. So können Sie 5 Felder erhalten, wobei die letzten zwei eine leere Zeichenfolge sind, {"field1", "field2", "field3", "", ""}.

+0

Sie sollten auch erklären, warum Ihre Lösung funktioniert (zum Beispiel, wie die "-1" hilft). – brimborium

+0

Ist das jetzt ok? Ich hoffe es. Danke für deinen Rat. – Happy3

+0

@ Happy3: Sie gaben einen Link zu java1.4 doc. sollten wir nicht auf die neueste Version verweisen? :) – nir

6

Nun niemand antwortete - was teilweise die Frage ist: die Eingabe-Zeichenfolge enthält elf Felder (so viel kann abgeleitet werden), aber wie viele Tabs? Die meisten möglicherweise genau 10. Dann ist die Antwort

String s = "\t2\t\t4\t5\t6\t\t8\t\t10\t"; 
String[] fields = s.split("\t", -1); // in your case s.split("\t", 11) might also do 
for (int i = 0; i < fields.length; ++i) { 
    if ("".equals(fields[i])) fields[i] = null; 
} 
System.out.println(Arrays.asList(fields)); 
// [null, 2, null, 4, 5, 6, null, 8, null, 10, null] 
// with s.split("\t") : [null, 2, null, 4, 5, 6, null, 8, null, 10] 

Wenn die Felder enthalten Registerkarten geschieht dies nicht wie erwartet funktionieren, natürlich.
Das -1 bedeutet: Wenden Sie das Muster so oft wie erforderlich an - so werden nachgestellte Felder (das 11.) beibehalten (als leere Zeichenfolgen ("") wenn abwesend, die explizit zu null gedreht werden müssen).

Wenn auf der anderen Seite gibt es keine Registerkarten für die fehlenden Felder - so "5\t6" ist eine gültige Eingabe-Zeichenfolge, die nur die Felder 5,6 enthält - gibt es keine Möglichkeit, die fields[] über Split zu bekommen.

+0

Es ist nicht als akzeptiert markiert, da das OP nach dem Stellen der Fragen nie wieder auf die Seite zurückkehrte. –

1

Ich hatte gerade die gleiche Frage und bemerkte die Antwort in einer Art Tutorial. In der Regel müssen Sie die zweite Form der Split-Methode verwenden, mit dem

split(regex, limit)

Hier ist die vollständige Tutorial http://www.rgagnon.com/javadetails/java-0438.html

Wenn Sie einige negative Zahl für den Parameter limit gesetzt werden Sie leere Strings erhalten im Array, wo die tatsächlichen Werte fehlen. Um dies zu verwenden, sollte Ihre ursprüngliche Zeichenfolge zwei Kopien des Trennzeichens haben, d. H. Sie sollten \ t \ t haben, wo die Werte fehlen.

this helps :)