Java while循环内使用BufferedReader出现流关闭错误如何解决?
问题原因及修复方案
存在的核心问题
- 字符串不可变导致替换失效:Java中
String是不可变类,str.replace("INSERT", answer)只会返回新字符串,原列表中的内容不会被修改,你没有把替换后的新值写回列表,替换逻辑相当于完全没生效 - 替换计数逻辑错误:嵌套循环的结构下,每次遍历整个列表遇到INSERT就给
modificater加1,既不会在替换完2个后及时停止,还可能重复替换同一个位置的INSERT占位符 - 流关闭逻辑不规范:你只手动关闭了
reader和外层的writer,包装流BufferedWriter没有正常关闭,同时没有做异常兜底,一旦中间代码报错流就无法正常关闭,多次循环后就会出现流被异常占用、提前关闭的问题 - 读写编码不一致:读取文件时指定了UTF-8编码,写入时用
FileWriter默认字符集,和读取编码不一致,可能导致后续循环读取时乱码甚至读不出内容,也就是你遇到的line为null、content为空的情况 - Scanner重复创建资源泄漏:每次循环都新建
Scanner实例,会导致输入流资源重复占用,应该全局只创建一次
修复后的代码
import java.nio.charset.StandardCharsets; // 全局只创建一次Scanner private Scanner enter = new Scanner(System.in); public void script() throws IOException { while(index*5 <= array.size()) { List<String> content = new ArrayList<>(); int modificater = 1; int position = (((index-1)*5)+4); // 用try-with-resources语法自动关流,避免手动关流遗漏问题 try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) { String line; while((line = reader.readLine()) != null) { content.add(line); } } // 提前判断列表长度避免下标越界 if (content.size() >= position) { System.out.println(content.get(position - 1)); } String answer = enter.nextLine(); // 修正替换逻辑,替换完2个占位符就终止循环 for (int i = 0; i < content.size() && modificater < 3; i++) { String str = content.get(i); if (str.contains("INSERT")) { // 把替换后的新字符串写回列表 content.set(i, str.replaceFirst("INSERT", answer)); modificater++; } } // 写入同样用try-with-resources自动关流,指定UTF-8编码和读取保持一致 try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) { for(String str : content) { bw.write(str); bw.newLine(); } } index++; } // 所有逻辑执行完成后再关闭Scanner enter.close(); }
额外注意点
- 操作文件前建议先备份原文件,避免写入错误导致内容丢失
- 可以在读取文件完成后先判断
content.isEmpty(),提前捕获文件读空的异常,避免直接调用get方法触发下标越界
内容的提问来源于stack exchange,提问作者Lupitrum
相关产品推荐
相关产品推荐

