Een csv-bestand splitsen met aanhalingstekens als tekstscheidingsteken met String.split()

Ik heb een door komma’s gescheiden bestand met veel regels die lijken op de onderstaande.

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

Aanhalingstekens worden gebruikt om te ontsnappen aan de komma met scheidingstekens die worden gebruikt om meerdere waarden weer te geven.

Hoe splits ik nu de bovenstaande waarde op het kommascheidingsteken met behulp van String.split()als dat al mogelijk is?


Antwoord 1, autoriteit 100%

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

Uitvoer:

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

Antwoord 2, autoriteit 11%

Omdat uw probleem/vereisten niet zo complex zijn, kan een aangepaste methode worden gebruikt die meer dan 20 keer sneller werkt en dezelfde resultaten oplevert.
Dit is variabel op basis van de gegevensgrootte en het aantal geparseerde rijen, en voor meer gecompliceerde problemen is het gebruik van reguliere expressies een must.

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

}

Op mijn eigen computer levert dit:

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.]

Antwoord 3, autoriteit 5%

Als je strings allemaal goed gevormd zijn, is het mogelijk met de volgende reguliere expressie:

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

De uitdrukking zorgt ervoor dat een splitsing alleen voorkomt bij komma’s die worden gevolgd door een even (of nul) aantal aanhalingstekens (en dus niet tussen dergelijke aanhalingstekens).

Desalniettemin kan het gemakkelijker zijn om een ​​eenvoudige niet-regex-parser te gebruiken.

Other episodes