2013-04-01 19 views
40

Birden çok satıra ayrılmış virgülle ayrılmış bir dosyam var.String.split() kullanarak metin sınırlayıcı olarak tırnak işaretleri içeren bir csv dosyasını bölme

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

Tırnaklar, birden çok değeri temsil etmek için kullanılan sınırlayıcı virgülden kurtulmak için kullanılır.

Şimdi yukarıdaki değeri String.split() kullanarak virgül sınırlayıcıda nasıl ayırırım?

+2

Neden String.split kullanmakta ısrar edersiniz? Bu örnek için daha iyi seçenekler var mı? Csv dosyasını okumak için – user949300

cevap

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

Çıktı:

Sorununuz/gereksinimleri tüm bu karmaşık özel bir yöntemi daha hızlı üzerinde 20 kat yapar ve aynı sonuçları ürettiğini kullanılabilir değildir gibi
[Sachin, , M, "Maths,Science,English", Need to improve in these subjects.] 
+13

+ 1 bu çok serin regex. Bunu daha önce görmedim, ama işe yarıyor! Bu kadar iyi hissediyorum ki sana bir ödül vereceğim :) (Not: ödül sürecinin tamamlanması için günler geçiyor) – Bohemian

+5

Bu regex'in ne yaptığını anlamak biraz zamanımı aldı. Çok sayıda alıntıyla (veya tırnaklarda) takip edilen virgüllerle eşleşmesinin açıklamasını bana büyük ölçüde yardımcı olurdu. Yani bu çalışır çünkü virgülün içindeki tırnaklar (yani, eşleştirmek istemediğimiz/ayırmak istemediklerimiz), aralarında ve satırın sonu arasında tek sayıda tırnak bulunmalıdır. Aynı zamanda, verilerin veriden kaçmış olması durumunda bunun işe yaramayacağına inanıyorum. – glyphx

+1

Bunu yapmak için s.split (', (? = ([^ \ "] * \" [^ \ "] * \") * [^ \ "] * $)', -1) sonunda dizeleri http://stackoverflow.com/questions/13939675/java-string-split-i-want-it-to-include-the-empty-strings-at-the-end – kctang

6

Dizeleriniz tüm aşağıdaki düzenli ifade ile mümkündür iyi biçimli ise:

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

ifadesi bölünmüş sadece eşit bir (veya sıfır) sayısına göre takip virgül olarak sağlanıp alıntılar (ve böylece böyle tırnak içinde değil). Bununla birlikte, basit bir regex olmayan ayrıştırıcı kullanmak daha kolay olabilir.

+0

ince çalışıyor .if formatı var ise. 987663, seepzBranch, "Seepz mumbai, andheri", "yakın infra, düz no 23, raghilla mall thane", seepz, –

9

. Bu, veri boyutuna ve ayrıştırılan satır sayısına bağlı olarak değişkendir ve normal ifadeleri kullanan daha karmaşık sorunlar için bir zorunluluktur. Kendi bilgisayarda

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

}

bu üretir:

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 Bu, 'String.split()' kullanarak bir çözüm için özel olarak soran soruyu yanıtlamaz. Bir yana, java hakkında çok az şey bilen biri tarafından yazılmış kodun ayırt edici özelliklerinden biri de 'Vector' kullanımıdır. – Bohemian

+4

Lütfen bu durumda neden Vector'in yerine ArrayList kullanmanın daha avantajlı olacağını açıklayın (iplik güvenliğinden kaynaklanan performans isabeti hariç). Ayrıca, nezaketiniz, kaba olan birinin ayırt edici özelliklerinden biri olan bazı işleri de kullanabilir. –

+0

Kaba davranmıyordum; sadece olgusal. İşte küçük bir ipucu ... 'Vector' * değil * threadafe. Bu kırılmış bir sınıf, bu yüzden kimsenin, ve gerçekten * kimsenin * demek olduğunu, gerçek dünyada kullandığını. Sadece toplam yeni başlayanlar bunu kullanıyor, benim tahminim, ders notlarının on yıl öncesine ait olması ve özellikle Vector'in kullanımını savunan öğretim görevlilerinin, akademide dokunma ve eski atasözü tutmak için çok fazla zaman harcadıklarından " o, öğretmek "hala doğrudur. – Bohemian

İlgili konular