操作BufferedReader后,OpenCSV的CSVReaderBuilder创建读取器返回null
问题分析与修复
你遇到的问题根源有两个:
1. BufferedReader流被提前耗尽
调用buffReader.lines().forEach()时,会一次性读取并遍历BufferedReader的所有行,这个操作会把流的指针移动到末尾。后续用这个已经被读完的BufferedReader创建CSVReader时,自然读取不到任何数据,返回null。
2. String不可变导致预处理无效
Java的String是不可变对象,你在lambda里执行t = t.concat(";")只是给局部变量t重新赋值了一个新的String对象,原流中的行内容完全没有被修改。就算流没被耗尽,这种预处理也起不到补全列的作用。
修复后的代码
正确的做法是把处理后的行重新包装成一个新的Reader,再传给CSVReaderBuilder:
FileInputStream is; try { is = new FileInputStream(fileName); InputStreamReader isr = new InputStreamReader(is, charSet); BufferedReader buffReader = new BufferedReader(isr); // 处理行:补全列数,然后收集为字符串 String processedContent = buffReader.lines() .map(line -> { String[] cols = line.split(";"); if (cols.length == 13) { return line.concat(";"); } return line; }) .collect(Collectors.joining("\n")); // 用处理后的内容创建新的Reader BufferedReader processedReader = new BufferedReader(new StringReader(processedContent)); // 初始化CSVParser和CSVReader final CSVParser parser = new CSVParserBuilder() .withSeparator(separator) .build(); reader = new CSVReaderBuilder(processedReader) .withCSVParser(parser) .build(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { // 补充处理IO异常 e.printStackTrace(); }
额外说明
如果CSV文件非常大,用Collectors.joining会把整个文件内容加载到内存,可能导致内存溢出。这种情况下可以用PipedReader和PipedWriter来异步处理流,避免内存占用过高:
// 示例:大文件流式处理 PipedReader pipedReader = new PipedReader(); PipedWriter pipedWriter = new PipedWriter(pipedReader); new Thread(() -> { try (BufferedReader br = new BufferedReader(new InputStreamReader(is, charSet))) { br.lines().forEach(line -> { try { String[] cols = line.split(";"); if (cols.length == 13) { pipedWriter.write(line.concat(";\n")); } else { pipedWriter.write(line + "\n"); } } catch (IOException e) { e.printStackTrace(); } }); } catch (IOException e) { e.printStackTrace(); } finally { try { pipedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); // 用pipedReader创建CSVReader final CSVParser parser = new CSVParserBuilder() .withSeparator(separator) .build(); reader = new CSVReaderBuilder(pipedReader) .withCSVParser(parser) .build();
内容的提问来源于stack exchange,提问作者sven
相关产品推荐
相关产品推荐

