2012-02-25 72 views
-1

我想優化我的文件閱讀器功能,但不確定是否最佳做法是在try循環之外聲明空值。另外,循環和追加字符到Stringbuffer被認爲是不好的做法?我想在這裏使用異常處理,但也許最好使用另一種結構?任何建議最受歡迎,謝謝。Filereader null聲明和附加最佳做法

public String readFile(){ 
File f = null; 
FileReader fr = null; 
StringBuffer content = null; 
try{ 
f = new File("c:/test.txt"); 
fr = new FileReader(f); 
int c;   
while((c = fr.read()) != -1){    
if(content == null){ 
content = new StringBuffer(); 
} 

content.append((char)c); 
     } 

fr.close();   
    } 
catch (Exception e) { 
throw new RuntimeException("An error occured reading your file"); 
    }  
    return content.toString(); 
} 

}

回答

3

建議:

  1. 縮進你的代碼正確。你問題中的東西看起來像狗的早餐。

  2. 您不需要在try/catch塊中初始化f。構造函數不能像你使用它的方式拋出一個Exception

  3. 實際上,你根本不需要聲明它。只需內聯new File(...)即可。

  4. 事實上,你甚至不需要那樣做。使用FileReader(String)構造函數。

  5. 在循環內初始化StringBuffer並沒有意義。潛在的性能優勢很小,只適用於文件爲空或不存在的邊緣情況。在所有其他情況下,這是一種反優化。

  6. 別抓Exception。捕獲您希望拋出的異常,並允許傳播所有其他異常。意料之外的異常將會由於程序中的錯誤而產生,並且需要與其他方式進行不同的處理。

  7. 當你發現異常時,不要丟棄證據。對於意外的異常,可以打印/記錄異常,其消息及其堆棧跟蹤,或將其作爲拋出異常的「原因」傳遞。

  8. FileReader應在finally條款中關閉。在您的代碼版本中,如果在創建對象之後和調用close()之前發生異常,則不會關閉FileReader。這將導致泄漏的文件描述符,並且可能會在您的應用程序中稍後導致問題。

  9. 更好的是,使用新的Java 7「try with resource」語法來自動關閉「資源」(見下文)。

  10. 您正在從文件中一次讀取一個字符。這是非常低效的。你需要或者包裹ReaderBufferedReader,或使用(例如)read(char[], int, int)

  11. 使用StringBuilder,而不是StringBuffer一次讀取大量字符的......除非你需要一個線程安全的字符串彙編。

  12. RuntimeException包裝異常是不好的做法。它使呼叫者很難處理特定的異常......如果需要...甚至使印刷體面的診斷更加困難。 (這假定你喜歡你的代碼確實沒有扔掉原來的例外)。

注意:如果你按照點8的建議,而不是9,你會發現,fr到初始化如果在try塊中打開文件,則需要null


這是我怎麼會這樣寫:

public String readFile() throws IOException { 
    // Using the Java 7 "try with resource syntax". 
    try (FileReader fr = new FileReader("c:/test.txt")) { 
    BufferedReader br = new BufferedReader(fr); 
    StringBuilder content = new StringBuilder(); 
    int c;   
    while ((c = br.read()) != -1) {    
     content.append((char)c); 
    } 
    return content.toString(); 
    } 
} 

進一步優化是使用File.length()找出文件大小(以字節爲單位)是並用其作爲初始大小StringBuilder。但是,如果文件通常很小,這可能會使應用程序變慢。

+0

'try(FileReader fr = new FileReader(「c:/test.txt」))'這在Java中是否合法?嘗試沒有抓住?嘗試使用參數?另外,如果你有一個try/catch塊,爲什麼要拋出IOException呢?最後,當您返回內容時,內容超出範圍。 – 2012-02-25 03:36:24

+0

它在Java 7語法中是合法的。這在Java 6或更早版本中不起作用。看到這裏:http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html – 2012-02-25 04:14:52

+0

@RyanAmos - 1)是的,它是合法的Java 7語法。 2)是的,嘗試沒有捕獲是合法的......見1)。 3)是的,見1)。 4)因爲我不捕獲IOException。 5)哎呀......我會解決這個問題的。 – 2012-02-25 04:57:11

0
public String readFile() { 
    File f = new File("/Users/Guest/Documents/workspace/Project/src/test.txt"); 
    FileReader fr = null; 
    BufferedReader br = null; 
    StringBuilder content = new StringBuilder();; 
    try { 
     fr = new FileReader(f); 
     br = new BufferedReader(fr); 
     //int c; 
     //while ((c = fr.read()) != -1) { 
      //content.append((char) c); 
     //} 
     String line = null; 
     while((line = br.readLine()) != null) { 
      content.append(line); 
     } 
     fr.close(); 
     br.close(); 
    } catch (Exception e) { 
     // do something 

    } 
    return content.toString(); 
} 

使用緩衝讀取器,你會得到70%+的改進,使用字符串生成器而不是字符串緩衝區,除非你需要同步。

跑了一個10MB的文件50次,取平均值

  • 沒有必要把任何不需要的異常處理中試
  • 沒有必要,如果子句,因爲這將是真正的只有一次,所以你浪費時間 - 檢查每個字符
  • 沒有運行時異常拋出。

結果: 最快組合到最慢:

  1. 字符串生成器和緩衝讀取器一行一行:211毫秒
  2. 串緩衝器和緩衝讀取器一行一行:213毫秒
  3. 字符串生成器和緩衝讀取器字符char:348 ms
  4. 字符串緩衝區和緩衝讀取器char:char:372 ms
  5. string bui由焦lder連續和文件讀取字符:878
  6. 字符串緩衝區和文件讀取字符的字符:935毫秒
  7. 字符串:極其緩慢

所以使用字符串生成器+緩衝的讀者,並使其通過讀取線線以獲得最佳效果。

+0

@StephenC,同意!從測試錯誤的文件路徑中將它留在那裏:) – Isaac 2012-02-25 05:35:04