我有一个逗号分隔的文件,其中有许多类似下面的行。
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.]
?:
添加到内部组中,因此完整表达式变为s.split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/);
。 - Marty Neal由于您的问题/需求并不是非常复杂,可以利用一种自定义方法来执行,它比原方法快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.]
String.split()
解决方案。顺带一提,使用 Vector
是一个对 Java 了解很少的人所编写的代码的标志之一。 - BohemianVector
不是线程安全的。它是一个有缺陷的类,这就是为什么没有人,我真的是没有人在现实世界中使用它。只有完全的初学者才会使用它,我猜测这是因为演讲笔记已经过时十年了,特别是那些提倡使用Vector的讲师已经在学术界呆太久,老话"如果你做不到,就去教别人做"仍然成立。 - Bohemiansplit()
),我会首先查找现有的库,对于CSV解析,有很多选择。 - Bohemian如果你的字符串都是规范的,可以使用以下正则表达式:
String[] res = str.split(",(?=([^\"]|\"[^\"]*\")*$)");
这个表达式确保分割仅发生在逗号后面跟随偶数(或零)引号的位置(因此不在这些引号内部)。
然而,使用简单的非正则表达式解析器可能更容易。
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));
}