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

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

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

引号用于转义用于表示多个值的分隔符。

现在如何尽可能地使用String.split()在逗号分隔符上分割上面的值?

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

由于您的问题/要求不是那么复杂,所以可以使用自定义方法,其执行速度超过20倍并产生相同的结果。 这是根据数据大小和parsing的行数而变化的,使用正则expression式的更复杂的问题是必须的。

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

如果你的string都是格式正确的,可以使用下面的正则expression式:

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

该expression式确保分割仅在逗号后面出现偶数(或零)引号(因此不在此类引号内)。

不过,使用简单的非正则expression式parsing器可能更容易。