首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java 文件讀寫:循環結束後變量為 null 是正常邏輯,非 Bug

     編輯:程式設計綜合問答

代碼現場

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();

為什麼 s 是 null?

while ((s = br.readLine()) != null) 的執行邏輯:

  1. 調用 br.readLine() 讀取下一行。
  2. 將返回值賦給 s。
  3. 判斷 s != null。
  4. 若 **true** → 執行循環體;若 **false** → **退出循環**,但 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-with-resources (Java 7+)

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

延伸:為什麼原代碼寫入 test2.txt 可能「少最後換行」?

  • 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 代碼更簡潔、安全、自動換行。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved