前提:这里考虑的各个单元格数据都不为空。
一、背景
实际的csv文件是用英文逗号分隔的,是一个简单的文本,但是如果单元格内的数据本身就包含英文逗号呢?

以上这种情况,保存的文本大概是这个样子:
张三,"3500,4500","唱歌,游泳,骑马,"
二、解析
下面使用java进行手动解析:
public class App {
public static void main(String[] args) {
// 张三,"3500,4500","唱歌,游泳,骑马,"
final String str = "张三,\"3500,4500\",\"唱歌,游泳,骑马,\"";
System.out.println(str);
final char[] arr = str.toCharArray();
int start = 0;
// 表示一个单元格内的数据就包含,
boolean complex = false;
int len = arr.length;
for (int i = 0; i < len; i++) {
char c = arr[i];
if (c == '"') { // 表示一个复合体的开始或者结束
if (complex) {
// 已经设置过complex标志,说明当前是一个复合体的结束"
final String item = new String(arr, start, i - start);
System.out.println(item);
complex = false;
i++;
} else {
// 未设置过complex标志,说明当前是一个复合体的开始"
start = i + 1;
complex = true;
}
} else if (c == ',' && !complex) { // 一个普通单元格的结束
final String item = new String(arr, start, i - start);
System.out.println(item);
start = i + 1;
}
}
}
}
控制台打印的内容:
张三,"3500,4500","唱歌,游泳,骑马,"
张三
3500,4500
唱歌,游泳,骑马,
三、思路
名词解释:
复合体:这里指的是数据中就包含英文逗号,的单元格。
普通单元格:这里指的是数据中不包含英文逗号,的单元格。
解析张三,"3500,4500","唱歌,游泳,骑马,"这行csv数据,基本原理还是将它转换为char[]字符数组,从头到尾逐个字符查看,对特殊字符进行标记、记录,这里特殊标记包括:
- 英文逗号
,,它可能表示一个普通单元格的结束,也可能只是复合体中的一个普通字符 - 英文分号
",它用来将一个复合体包裹起来,表示一个复合体的开始或者是结束
对于一个单元格的数据,我需要知道它从哪里开始,即这里的start变量值,到哪里结束,这里就是检测到结束的i的位置,然后从arr字符数组中构建一个String,就得到了一个单元格的数据。
对于普通字符,不需要标记,跳过即可,考虑上面提到的两个特殊标志:
- 对于
,来说,如果当前的complex为false,说明之前并没有碰到复合体,那么它就是一个单元格数据的结束了,可以构建一个String,并且可以预见下一个字符就应该是另一个单元格数据的开始,那么就需要将它设置为start = i + 1,其实它并不完全正确,因为下一个有可能是特殊标记",但是它会被下面的这种情况所修正 - 对于
"来说,它有可能表示复合体的开始或者结束,这里使用一个布尔值complex来进行区分,如果complex的值为true,说明当前遇到一个"标记,并且之前也碰到一个"才会使得complex的值为true,即可以构建一个final String item = new String(arr, start, i - start)。同时需要设置complex的值为false,让它失效,同时紧挨着的下一个,没有意义,手动跳过它:i++。如果complex的值为false,说明是第一个遇到",表示复合体的开始,只需要设置start = i + 1,同时设置complex = true使之生效。
that’s all
thanks for reading~
111
本文详细讲述了在CSV文件中遇到包含英文逗号的数据如何使用Java进行解析,通过实例演示了如何识别复合体和普通单元格,并展示了关键的逻辑和标记方法。
1315

被折叠的 条评论
为什么被折叠?



