2010-05-27 49 views
2

寫了一個基本的文件處理程序一個Java家庭作業,而當我接到任務後,我有一些注意事項有關未能趕上了幾個例子:Java文件處理,我做錯了什麼?

  • 從文件緩衝區可能已空。
  • 文件未找到
  • 文件流沒有關閉

這裏是用來打開文件的代碼塊:

/** 
* Create a Filestream, Buffer, and a String to store the Buffer. 
*/ 
FileInputStream fin = null; 
BufferedReader buffRead = null; 
String loadedString = null; 

/** Try to open the file from user input */ 
try 
{ 
    fin = new FileInputStream(programPath + fileToParse); 
    buffRead = new BufferedReader(new InputStreamReader(fin)); 
    loadedString = buffRead.readLine(); 
    fin.close(); 
} 
/** Catch the error if we can't open the file */ 
catch(IOException e) 
{ 
    System.err.println("CRITICAL: Unable to open text file!"); 
    System.err.println("Exiting!"); 
    System.exit(-1); 
} 

了一句話,我從他身上了是fin.close();需要在finally塊,我根本沒有。但我認爲我創建try/catch的方式可以防止文件無法打開的問題。

讓我清楚幾件事情:這不是爲了當前的任務(不是試圖讓某人做我自己的工作),我已經創建了我的項目,並對它進行了評分。我自己並沒有完全理解我的教授的推理。最後,我沒有太多的Java經驗,所以我有點困惑爲什麼我的catch不夠好。

+2

雖然在一個長時間運行的程序中關閉系統資源是非常重要的(當然這是很好的做法),如果你打算在yo中調用'System.exit',是否關閉文件是一個有爭議的問題你的catch塊。 – jasonmp85 2010-05-27 18:57:03

+0

@ jasonmp85這就是我的想法,但是它看起來好像他希望我們把它標記爲好像它會一直在運行。這對我來說很有意義。 – Urda 2010-05-27 19:36:45

回答

7
  • 緩衝區從文件可能已空。

該文件可能爲空。也就是說,在打開文件時達到文件結束。 loadedString = buffRead.readLine()然後會返回null。

也許你應該添加類似if (loadedString == null) loadedString = "";

  • 文件有固定的這個沒有被發現

由於FileInputStream(String)構造函數可能拋出的文件中解釋一個FileNotFoundException。你做你的IOException子句捕捉這個(因爲FileNotFoundExceptionIOException),所以它的精細,但你也許可以這樣做:

} catch (FileNotFoundException fnfe) { 
    System.err.println("File not fonud!"); 
} catch (IOException ioex { 
    System.err.println("Some other error"); 
} 
  • 文件流沒有關閉

你確實打電話給fin.close(),它在正常情況下關閉文件流。也許他意味着它不是總是關閉。 readLine可能會拋出IOException,在這種情況下跳過close()。這就是原因在finally條款有它(這確保它被稱爲無論在try - 阻塞會發生什麼。(*)


(*)作爲@mmyers正確地指出,把close()finally塊中實際上是不夠的,因爲你在catch -block中調用System.exit(-1)如果這真的是所需的行爲,你可以在catch-clause中設置一個錯誤標誌,如果這個標誌是

+0

如果由於catch塊中的System.exit()而導致異常,finally子句將不會被執行。 – 2010-05-27 19:00:55

+0

好點!我沒有想到這一點!我會更新答案。 – aioobe 2010-05-27 19:02:51

+0

從技術上講,FileInputStream *的finalize方法會在終止時關閉流:-) – aioobe 2010-05-27 19:08:46

1

buffRead.readLine()拋出異常,您的FileInputStream會永遠關閉,還是會跳過該行? finally塊的用途是,即使在特殊情況下,finally塊中的代碼也會執行。

3

但是如果您的程序在try塊的第二行或第三行上拋出異常,該怎麼辦?

buffRead = new BufferedReader(new InputStreamReader(fin)); 
loadedString = buffRead.readLine(); 

到此爲止,文件句柄已打開並分配給fin。您可以捕獲異常,但文件句柄將保持打開狀態。

你要的fin.close()聲明移到finally塊:

} finally { 
    try { 
     if (fin != null) { 
      fin.close(); 
     } 
    } catch (IOException e2) { 
    } 
} 
+1

我想你應該在試圖關閉它之前添加一個'if(fin!= null)'(如果該文件不存在)。 – Kru 2010-05-27 19:01:29

+0

謝謝@Chris,已修復。 – mob 2010-05-27 19:10:02

+0

,或者再次使用apache commons(本例中爲io),只寫一行:'IOUtils。closeQuietly(fin);',這正是你正在做的很少(本地)代碼http://commons.apache.org/io/apidocs/org/apache/commons/io/IOUtils.html#closeQuietly% 28java.io.InputStream%29 – 2010-05-27 19:39:48

0

除打開文件外,還有很多其他錯誤可能發生

最後,您最終可能會定義一個定義或不定義的fin,您必須防止出現空指針錯誤,並且不要忘記關閉文件會引發新的異常。

我的建議是捕捉到了這個在一個單獨的程序,讓的IOExceptions飛出來的:

private String readFile() throws IOException { 
    String s; 
    try { 
    fin = new FileInputStream(programPath + fileToParse); 
    buffRead = new BufferedReader(new InputStreamReader(fin)); 
    s = buffRead.readLine(); 
    fin.close(); 
    } finally { 
    if (fin != null { 
     fin.close() 
    } 
    } 
    return s 
} 

,然後在你需要它:

try { 
    loadedString = readFile(); 
} catch (IOException e) { 
    // handle issue gracefully 
} 
+0

無論是否引發異常,都會執行finally代碼塊。因此,在正常情況下,你有一個冗餘的'fin.close()'。 'try'塊中的那個可以被刪除。 – 2010-05-27 19:14:49

+0

gee,這個頁面上幾乎每個問題都有一個apache commons解決方案。使用FileUtils.readFileToString(文件),它更短,你可以重新調用它。 http://commons.apache.org/io/apidocs/org/apache/commons/io/FileUtils.html#readFileToString(java.io.File) – 2010-05-27 19:42:43