2013-04-01 8 views
40

Ich habe eine durch Kommas getrennte Datei mit vielen Zeilen ähnlich einer unten.Aufteilen einer csv-Datei mit Anführungszeichen als Text-Trennzeichen mit String.split()

Sachin,,M,"Maths,Science,English",Need to improve in these subjects. 

Anführungszeichen werden verwendet, um das Begrenzerkomma zu trennen, das zur Darstellung mehrerer Werte verwendet wird.

Nun, wie teile ich den obigen Wert auf das Komma Trennzeichen mit String.split() wenn überhaupt möglich?

+2

Warum bestehen Sie String.split weiterverwenden? Es gibt viel bessere Möglichkeiten für dieses Beispiel? – user949300

Antwort

134
public static void main(String[] args) { 
    String s = "Sachin,,M,\"Maths,Science,English\",Need to improve in these subjects."; 
    String[] splitted = s.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"); 
    System.out.println(Arrays.toString(splitted)); 
} 

Ausgang:

[Sachin, , M, "Maths,Science,English", Need to improve in these subjects.] 
+13

+1 Dies ist ein sehr cooler Regex. Ich habe das vorher nicht gesehen, aber es funktioniert! Ich denke, das ist so gut, dass ich dir eine Belohnung zusprechen werde :) (Anmerkung: Der Kopfgeldprozess dauert viele Tage) – Bohemian

+5

Es hat eine Weile gedauert, bis ich herausgefunden hatte, was diese Regex tat. Es hätte mir sehr geholfen, die Erklärung zu haben, dass es Kommas abgleicht, denen eine gerade Anzahl von Anführungszeichen (oder keine Anführungszeichen) folgt. Das funktioniert also, weil Kommas in Anführungszeichen (d. H. Diejenigen, die wir nicht abgleichen wollen) eine ungerade Anzahl von Anführungszeichen zwischen ihnen und dem Ende der Zeile haben sollten. Es könnte auch erwähnenswert sein, dass dies nicht funktionieren würde, wenn die Daten darin enthalten wären. – glyphx

+1

Tun Sie dies s.split (', (? = ([^ \ "] * \" [^ \ "] * \") * [^ \ "] * $)', -1) wenn Sie leer halten wollen Strings am Ende http://stackoverflow.com/questions/13939675/java-string-split-i-want-it-to-include-the-empty-strings-at-the-end – kctang

6

Wenn die Saiten sind alle gut ausgebildet ist es möglich, mit dem folgenden regulären Ausdruck:

String[] res = str.split(",(?=([^\"]|\"[^\"]*\")*$)"); 

Der Ausdruck stellt sicher, dass eine Spaltung nur bei Kommas auftritt, die durch eine gerade (oder Null) Zahl der gefolgt werden Zitate (und somit nicht in solchen Anführungszeichen).

Dennoch kann es einfacher sein, einen einfachen Nicht-Regex-Parser zu verwenden.

+0

für das Lesen von CSV-Datei funktioniert es gut. Wenn Sie diese Art von Format haben 987663, SeepzBranch, "Seepz Mumbai, Andheri", "in der Nähe von Infra, Wohnung Nr. 23, Raghilla Mall Thane", Seepz, –

9

Als Ihr Problem/Anforderungen sind nicht so komplex eine benutzerdefinierte Methode verwendet werden kann, die schneller über 20 Mal durchführt und erzeugt die gleichen Ergebnisse. Dies ist eine Variable basierend auf der Datengröße und der Anzahl der analysierten Zeilen und für kompliziertere Probleme mit regulären Ausdrücken ein Muss.

import java.util.Arrays; 
import java.util.ArrayList; 
public class SplitTest { 

public static void main(String[] args) { 

    String s = "Sachin,,M,\"Maths,Science,English\",Need to improve in these subjects."; 
    String[] splitted = null; 

//Measure Regular Expression 
    long startTime = System.nanoTime(); 
    for(int i=0; i<10; i++) 
    splitted = s.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"); 
    long endTime = System.nanoTime(); 

    System.out.println("Took: " + (endTime-startTime)); 
    System.out.println(Arrays.toString(splitted)); 
    System.out.println(""); 


    ArrayList<String> sw = null;   
//Measure Custom Method 
      startTime = System.nanoTime(); 
    for(int i=0; i<10; i++) 
    sw = customSplitSpecific(s); 
    endTime = System.nanoTime(); 

    System.out.println("Took: " + (endTime-startTime)); 
    System.out.println(sw);   
} 

public static ArrayList<String> customSplitSpecific(String s) 
{ 
    ArrayList<String> words = new ArrayList<String>(); 
    boolean notInsideComma = true; 
    int start =0, end=0; 
    for(int i=0; i<s.length()-1; i++) 
    { 
     if(s.charAt(i)==',' && notInsideComma) 
     { 
      words.add(s.substring(start,i)); 
      start = i+1;     
     } 
     else if(s.charAt(i)=='"') 
     notInsideComma=!notInsideComma; 
    } 
    words.add(s.substring(start)); 
    return words; 
} 

}

auf meinem eigenen Computer erzeugt dies:

Took: 6651100 
[Sachin, , M, "Maths,Science,English", Need to improve in these subjects.] 

Took: 224179 
[Sachin, , M, "Maths,Science,English", Need to improve in these subjects.] 
+0

-1 Dies beantwortet nicht die Frage, die speziell nach einer Lösung mit 'String.split()' fragt. Nebenbei bemerkt, eines der Markenzeichen von Code, der von jemandem geschrieben wurde, der nur wenig über Java weiß, ist die Verwendung von 'Vector'. – Bohemian

+4

Bitte erläutern Sie, warum es in dieser Situation vorteilhafter wäre, ArrayList anstelle von Vector zu verwenden (mit Ausnahme des Leistungseinbruchs aufgrund der Thread-Sicherheit). Auch Ihre Höflichkeit könnte etwas Arbeit gebrauchen, was eines der Kennzeichen von jemandem ist, der unhöflich ist. –

+0

Ich war nicht unhöflich; nur faktisch. Hier ist ein kleiner Tipp ... 'Vector' ist * nicht * threadsafe. Es ist eine kaputte Klasse, weshalb niemand, und ich meine wirklich * niemand *, es in der realen Welt benutzt. Nur totale Anfänger benutzen es, meine Vermutung ist, weil Vorlesungsvermerke zehn Jahre veraltet sind, und besonders, weil Dozenten, die den Gebrauch von Vector befürworten, zu viel Zeit in der Wissenschaft verbracht haben, um in Kontakt zu bleiben und das alte Sprichwort "Wenn du es nicht kannst es, lehre es "gilt immer noch. – Bohemian

Verwandte Themen