BufferedReader br = new BufferedReader(new FileReader("f:/test1.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("f:/test2.txt"));
PrintWriter out = new PrintWriter(bw);
String s;
while ((s = br.readLine()) != null) {
out.write(s);
}
out.flush();
System.out.println(s); // 輸出 null
out.println(s); // 寫入 null
br.close();
bw.close();
while ((s = br.readLine()) != null) 的執行邏輯:
br.readLine() 讀取下一行。s。s != null。s **已被賦值為 null**。因此,**循環正常結束的前提是 readLine() 返回 null**,此時 s 必然為 null。這是 Java 語言規定的賦值表達式語義,完全正常。
循環體內 out.write(s) 在每次讀取非 null 行時執行,**文件內容已正確複製到 test2.txt**。問題僅在於循環後錯誤地嘗試使用已為 null 的 s。
String s;
while ((s = br.readLine()) != null) {
out.write(s);
out.println(); // 若需保留換行,readLine 去掉了 \n
}
// 循環結束後 s 為 null,不可使用
out.flush();
// System.out.println(s); // 刪除或移入循環內
// out.println(s); // 刪除
br.close();
bw.close();
out.close();
try (BufferedReader br = new BufferedReader(new FileReader("f:/test1.txt"));
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("f:/test2.txt")))) {
String line;
while ((line = br.readLine()) != null) {
out.println(line); // println 自動加換行 + flush
}
} catch (IOException e) {
e.printStackTrace();
}
// 自動關閉資源,無需手動 close
readLine() **不返回行終止符**(\n 或 \r\n)。out.write(s) **不自動添加換行**。out.println(s) 或 out.write(s + System.lineSeparator())。while ((s = br.readLine()) != null) 結束時 s == null 是**語言特性,非 Bug**。文件複製邏輯正確,僅循環後誤用 s。改用 try-with-resources + println 代碼更簡潔、安全、自動換行。