遍历CSV文件匹配指定数值时Java代码无响应问题排查
问题描述
我有如下结构的CSV文件:
| car | score | description |
|---|---|---|
| Opel | 30 | 43 |
| Volvo | 500 | 434 |
| Kia | 50 | 3 |
| Toyota | 4 | 4 |
| Mazda | 5000 | 4 |
需求是:在文件中匹配50、500、5000这三个数值,当三者同时存在时,将该CSV文件移至invalid_files文件夹;否则移至processed文件夹。
我编写了如下Java代码:
File filesList[] = directoryPath.listFiles(textFileFilter); System.out.println("List of the text files in the specified directory:"); for(File file : filesList) { try { try (var br = new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16)){ List<CsvLine> beans = new CsvToBeanBuilder(br) .withType(CsvLine.class) .build() .parse(); Path originalPath = null; boolean found50 = false; boolean found500 = false; boolean found5000 = false; for (CsvLine item : beans) { originalPath = file.toPath(); if (item.getAvgMonthlySearches() != null) { if (item.getValue().compareTo(BigDecimal.valueOf(50)) == 0) { found50 = true; } if (item.getValue().compareTo(BigDecimal.valueOf(500)) == 0) { found500 = true; } if (item.getValue().compareTo(BigDecimal.valueOf(5000)) == 0) { found5000 = true; } } if(found50 == true && found500 == true && found5000 == true){ found50 = false; found500 = false; found5000 = false; // Move here file into new subdirectory when file is invalid Path copied = Paths.get(file.getParent() + "/invalid_files"); try { // Use resolve method to keep the "processed" as folder br.close(); Files.move(originalPath, copied.resolve(originalPath.getFileName()), StandardCopyOption.REPLACE_EXISTING); break; } catch (IOException e) { throw new RuntimeException(e); } } } if (file.exists()) { // Move here file into new subdirectory when file processing is finished Path copied = Paths.get(file.getParent() + "/processed"); try { // Use resolve method to keep the "processed" as folder br.close(); Files.move(originalPath, copied.resolve(originalPath.getFileName()), StandardCopyOption.REPLACE_EXISTING); break; } catch (IOException e) { throw new RuntimeException(e); } } } } catch (Exception e){ e.printStackTrace(); } Path originalPath = file.toPath(); System.out.println(String.format("Processed file : %s, moving the file to subfolder /processed", originalPath)); }
对应的CsvLine实体类:
@Getter @Setter public class CsvLine { @CsvBindByPosition(position = 2) private BigDecimal value; }
但运行上述代码后没有任何效果,请问代码存在什么问题?
代码问题分析
CSV列绑定位置错误
你的CSV结构中,目标数值所在的score是第二列(索引从0开始为position=1),但CsvLine中@CsvBindByPosition(position = 2)绑定的是第三列description,导致读取的value永远是描述列的内容,完全匹配不到目标数值。需将位置改为position=1。调用不存在的方法
CsvLine类中没有getAvgMonthlySearches()方法,这行代码会直接抛出NoSuchMethodError,但外层catch仅打印堆栈,若未查看控制台则无法发现该错误。需删除此判断,或替换为item.getValue() != null。文件移动逻辑存在多重问题
- 使用try-with-resources声明的
br会自动关闭,手动调用br.close()会导致后续操作报错; - 目标文件夹
invalid_files和processed如果不存在,Files.move会抛出异常,需先通过Files.createDirectories()确保文件夹存在; - 找到目标值移动文件后,循环
break但后续仍会执行if (file.exists())的判断,尝试移动已被移走的文件,引发错误。
- 使用try-with-resources声明的
标记位重置逻辑错误
当三个目标值都找到后,无需将found50、found500、found5000重置为false,此操作会导致逻辑混乱,直接跳出循环即可。编码不匹配可能导致解析失败
若CSV文件实际编码不是UTF-16,使用StandardCharsets.UTF_16读取会导致内容乱码,无法正确解析数值。建议确认文件编码,或尝试用UTF-8读取。
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

