CSV文件读写时userName字段重复添加逗号的问题求助
解决CSV读写中userName字段的多余逗号问题
问题现状
程序每次迭代会将对象变量保存到.csv文件并覆盖原有内容,遇到以下异常情况:
- 使用
read.next()读取userName时,字段为空会直接报错 - 使用
read.nextLine()读取时,多次保存后userName出现多余逗号(例如变成,,,Fred),推测是读取到了分隔符逗号 - 已设置
.useDelimiter(",")作为CSV分隔符,当前生成的CSV内容异常:
BE11,1.00,true,122123,,,,Fred BE12,1.00,false,0, BE13,1.00,false,0,
问题根源
read.next()的局限性:该方法会读取到下一个分隔符(逗号)为止,当userName为空时,后续无有效内容可读取,直接抛出NoSuchElementException。read.nextLine()的副作用:调用read.nextLong()后,Scanner指针停在该字段后的逗号位置,此时read.nextLine()会读取从当前位置到行尾的所有内容(包括逗号和换行符)。当userName为空时,会读取到,\n这类无效内容,再次写入时就会引入多余逗号。- 写入逻辑的小疏漏:PrintWriter代码中
write.println((bikeArrayList.get(i).getUserName());多了一个左括号,虽属笔误,但也可能干扰输出格式。
解决方案
方案1:修正Scanner读取逻辑,兼容空字段
调整分隔符规则,同时处理userName的空值情况:
// 把逗号和换行符都设为分隔符,避免跨行读取无效内容 read.useDelimiter(",|\\n"); while (read.hasNext()) { String ID = read.next().trim(); double BatteryCharge = read.nextDouble(); boolean inUse = read.nextBoolean(); long rentalStart = read.nextLong(); // 读取userName,为空时设为空字符串 String userName = read.hasNext() ? read.next().trim() : ""; // 过滤换行符带来的空内容 if (userName.equals("\n") || userName.isEmpty()) { userName = ""; } bikeArrayList.add(new Bike(ID, BatteryCharge, inUse, rentalStart, userName)); }
方案2:统一写入格式,避免多余逗号
写入时保证每行字段数一致,空userName直接写入空字符串:
for (int i = 0; i < bikeArrayList.size(); i++) { Bike bike = bikeArrayList.get(i); write.print(bike.getBikeId() + ","); write.print(bike.getBatteryCharge() + ","); write.print(bike.isInUse() + ","); write.print(bike.getRentalStart() + ","); // 空userName直接写空字符串,确保行尾格式正确 write.println(bike.getUserName() != null ? bike.getUserName() : ""); }
方案3:按行拆分字段(推荐)
跳过Scanner的自动分隔逻辑,手动按行读取并拆分字段,精准控制每个字段的读取:
// 按行读取CSV内容 while (read.hasNextLine()) { String line = read.nextLine().trim(); if (line.isEmpty()) continue; // 拆分字段时保留空值,避免丢失空的userName String[] fields = line.split(",", -1); if (fields.length >= 5) { String ID = fields[0].trim(); double BatteryCharge = Double.parseDouble(fields[1].trim()); boolean inUse = Boolean.parseBoolean(fields[2].trim()); long rentalStart = Long.parseLong(fields[3].trim()); String userName = fields[4].trim(); bikeArrayList.add(new Bike(ID, BatteryCharge, inUse, rentalStart, userName)); } }
这种方式完全规避了Scanner分隔符的陷阱,不管字段是否为空都能正确处理。
内容的提问来源于stack exchange,提问作者Eric Rebadona
相关产品推荐
相关产品推荐

