循环读取文件内容时触发Stream has already been operated upon or closed报错原因是什么
问题原因
- Java Stream属于一次性消费对象,仅支持执行一次终端操作(
forEach属于典型的终端操作),执行完成后流就会被标记为已关闭/已操作,无法再次复用。 - 你的代码逻辑是外层循环遍历替换规则map的每一组键值对,每次循环都调用一次
stream.forEach操作,第一次执行完stream.forEach后流就已经被关闭,第二次循环再调用时直接触发抛出对应的异常。 - 额外隐藏问题:
replaceAll方法接收的第一个参数是正则表达式,如果你的caracterMal是普通字符(比如特殊符号$、.之类),会触发正则匹配逻辑导致替换结果不符合预期,普通字符替换建议直接使用replace方法。
修复代码(推荐方案:流单次消费,每行应用全部替换规则)
该方案仅读取一次文件,性能更高,也符合Stream的使用规范:
String fileName = "C:\\Users\\xxxxx\\Downloads\\InformeModificacionesUnificado28102021-09.txt"; // File file = new File(fileName); // output = new BufferedWriter(new FileWriter(file)); try (Stream<String> stream = Files.lines(Paths.get(fileName))) { stream.forEach(x -> { String cadenaWena = x; // 每行内容依次应用所有替换规则 for (var entry : map.entrySet()) { cadenaWena = cadenaWena.replace(entry.getKey(), entry.getValue()); } System.out.println(cadenaWena); // 如果是写入文件记得加换行:output.newLine(); // output.write(cadenaWena); }); } catch (IOException e) { e.printStackTrace(); }
不推荐方案(多次读取文件,性能差):
如果你确实需要针对每一条替换规则单独遍历全量文件内容,可以每次遍历都重新生成Stream,避免复用已消费的流:String fileName = "C:\\Users\\xxxxx\\Downloads\\InformeModificacionesUnificado28102021-09.txt"; map.forEach((caracterMal, caracterBien) -> { try (Stream<String> stream = Files.lines(Paths.get(fileName))) { stream.forEach(x -> { String cadenaWena = x.replaceAll(caracterMal, caracterBien); System.out.println(cadenaWena); }); } catch (IOException e) { e.printStackTrace(); } });该方案会根据map的大小重复读取N次文件,IO开销大,仅适合特殊场景使用。
内容的提问来源于stack exchange,提问作者okjfokjrf
相关产品推荐
相关产品推荐

