使用String.split()将带引号的csv文件拆分为文本文件

unguejic  于 2023-09-27  发布在  其他
关注(0)|答案(5)|浏览(93)

我有一个逗号分隔的文件与许多行类似的一个下面。

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

引号用于转义用于表示多个值的分隔符逗号。
现在,如果可能的话,我该如何使用String.split()在逗号分隔符上分割上述值?

neekobn8

neekobn81#

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

输出量:

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

oxiaedzo2#

由于您的问题/需求并不那么复杂,因此可以使用自定义方法,其执行速度快20倍以上,并产生相同的结果。这取决于数据大小和分析的行数,对于更复杂的问题,必须使用正则表达式。

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

}
在我自己的电脑上,这会产生:

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

pexxcrt23#

如果您的字符串都是格式良好的,则可以使用以下正则表达式:

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

该表达式确保拆分仅发生在逗号后面跟有偶数(或零)个引号(因此不在此类引号内)。
然而,使用简单的非正则表达式解析器可能更容易。

ccgok5k5

ccgok5k54#

最喜欢的答案似乎是正确的,除非你有尾随逗号的情况。您应该在拆分上指定the limit argument

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

否则结果将不包括最后三列。

zrfyljdw

zrfyljdw5#

在处理CSV字符串时,我们需要知道以下几点。
1.行中的每个元组将以“(引号)”或“不”开头。a)如果它以“(引号)开始,那么它必须是特定列的值。B)如果它是直接启动的,那么它必须是头。例如:'Header 1,Header 2,Header 3,“value 1”,“value 2”,“value 3”';这里Header 1、Header 2、Header 3是列名,其余是值。
主要的一点,我们需要记住,而做分裂是你需要检查,吐是做正确与否。a)获取拆分值并检查值中的引号数量(计数必须为偶数)b)如果计数为奇数,则追加下一个拆分值。c)重复过程a、B直到引号相等。

相关问题