Java无第三方库读取CSV能否仅将逗号设为Scanner分隔符
问题背景
需要在不借助任何第三方库的前提下,仅使用逗号作为分隔符读取CSV文件。
例如需要读取人员姓名、签到时间、签退时间,对应CSV文件的行格式为:
John Doe, 09:00, 17:00
预期拆分得到三个独立token:"John Doe"、"09:00"、"17:00"。
问题复现
初始实现代码如下:
/* main method */ public static void main(String[] args) throws FileNotFoundException { // scanner object Scanner get = new Scanner(System.in); // set delimiter, read comma and single space as delimiter get.useDelimiter(", "); // prompt for file System.out.println("Provide a file name:"); File employeeRecords = new File(get.nextLine()); get = new Scanner(employeeRecords); // test run // read: employeeName, clockIn, lunchIn, lunchOut, clockOut // "Employee" is an object Employee $1 = new Employee(get.next(), get.next(), get.next(), get.next(), get.next()); // .timeWorked is a method of the "Employee" object System.out.println("\nEmployee $1: " + $1.name + ", minutes worked: " + $1.timeWorked); }
实际运行传入CSV文件时,之前设置的Scanner分隔符规则未生效。
测试用CSV文件仅包含一行内容:
John, 07:59, 12:00, 12:31, 17:00
连续调用5次get.next()得到的token为:
"John,""07:59,""12:00,""12:31,""17:00"
对应打印输出结果为:
Employee $1: John,, minutes worked: -1443
暂不考虑工时计算的逻辑bug,核心诉求为确认是否可以仅将逗号设置为Scanner的分隔符完成CSV读取。
问题根因
分隔符配置是在重新实例化Scanner对象之前设置的:最开始的useDelimiter作用于绑定标准输入流的Scanner实例,后续重新创建了绑定目标文件的Scanner新实例,旧实例的配置不会继承到新实例上,因此读取文件时实际使用的是Scanner默认的空白分隔符,才会把逗号保留在拆分出的token中。
修正方案
在完成文件绑定的Scanner实例化操作之后,再调用useDelimiter方法设置分隔符即可:
- 如果严格要求仅以逗号作为分隔符,直接传入参数
"," - 如果需要兼容逗号后带空格的常见CSV格式,可以传入正则表达式
",\\s*"作为分隔符,自动跳过逗号后的任意数量空白字符,不需要额外手动处理字段前后的空格。
修正后的核心代码片段:
File employeeRecords = new File(get.nextLine()); // 先实例化绑定目标文件的Scanner get = new Scanner(employeeRecords); // 再给读取文件用的Scanner实例设置分隔符 get.useDelimiter(",\\s*");
内容的提问来源于stack exchange,提问作者Xbox 360
相关产品推荐
相关产品推荐

