2016-04-28 49 views
2

我試圖做這樣的:Java代碼優化,替換文件中的所有字符

import java.io.*; 

public class ConvertChar { 
    public static void main(String args[]) { 
     Long now = System.nanoTime(); 
     String nomCompletFichier = "C:\\Users\\aahamed\\Desktop\\test\\test.xml"; 
     Convert(nomCompletFichier); 
     Long inter = System.nanoTime() - now; 
     System.out.println(inter); 
    } 

    public static void Convert(String nomCompletFichier) { 
     FileWriter writer = null; 
     BufferedReader reader = null; 
     try { 
      File file = new File(nomCompletFichier); 
      reader = new BufferedReader(new FileReader(file)); 

      String oldtext = ""; 
      while (reader.ready()) { 
       oldtext += reader.readLine() + "\n"; 
      } 
      reader.close(); 
      // replace a word in a file 
      // String newtext = oldtext.replaceAll("drink", "Love"); 

      // To replace a line in a file 
      String newtext = oldtext.replaceAll("&(?!amp;)", "&"); 

      writer = new FileWriter(file); 
      writer.write(newtext); 
      writer.close(); 

     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 
    } 

} 

但是上面的代碼需要更多的時間比創建兩個不同的文件來執行:

import java.io.*; 

public class ConvertChar { 
    public static void main(String args[]) { 
     Long now = System.nanoTime(); 
     String nomCompletFichier = "C:\\Users\\aahamed\\Desktop\\test\\test.xml"; 
     Convert(nomCompletFichier); 
     Long inter = System.nanoTime() - now; 
     System.out.println(inter); 
    } 

    private static void Convert(String nomCompletFichier) { 

     BufferedReader br = null; 
     BufferedWriter bw = null; 

     try { 
      File file = new File(nomCompletFichier); 
      File tempFile = File.createTempFile("buffer", ".tmp"); 

      bw = new BufferedWriter(new FileWriter(tempFile, true)); 
      br = new BufferedReader(new FileReader(file)); 

      while (br.ready()) { 
       bw.write(br.readLine().replaceAll("&(?!amp;)", "&") + "\n"); 
      } 

      bw.close(); 
      br.close(); 

      file.delete(); 
      tempFile.renameTo(file); 

     } catch (IOException e) { 
      // writeLog("Erreur lors de la conversion des caractères : " + e.getMessage(), 0); 
     } finally { 
      try { 
       bw.close(); 
      } catch (Exception ignore) { 
      } 
      try { 
       br.close(); 
      } catch (Exception ignore) { 
      } 
     } 
    } 

} 

有沒有辦法做第二個代碼而不創建臨時文件並減少執行時間?我正在做一個代碼優化。

+0

在第二個示例中,爲什麼不直接寫入目標文件?爲什麼你需要一個臨時文件? – Mifeet

+0

「在不創建臨時文件的情況下執行第二個代碼」:您的意思是使用臨時文件而不創建臨時文件? – Henry

+0

@Henry:我的意思是在不使用臨時文件的情況下替換文件中的所有字符。直接在文件中進行更改。 – tabby

回答

1

您的第一個示例中的主要罪魁禍首是您正在使用字符串串聯低效地構建oldtext,如here所述。這爲每個級聯分配一個新的字符串。 Java提供您StringBuilder建築字符串:

StringBuilder builder = new StringBuilder; 
    while(reader.ready()){ 
     builder.append(reader.readLine()); 
     builder.append("\n"); 
    } 
    String oldtext = builder.toString(); 

您也可以更換,當你建立你的文字StringBuilder。您的代碼的另一個問題是您shouldn't use ready()檢查文件中是否有剩餘內容 - 請檢查readLine()的結果。最後,關閉流應該在finally或嘗試與資源塊。結果可能是這樣的:

StringBuilder builder = new StringBuilder(); 
    try (BufferedReader reader = new BufferedReader(new FileReader(file))) { 
     String line = reader.readLine(); 
     while (line != null) { 
      builder.append(line.replaceAll("&(?!amp;)", "&")); 
      builder.append('\n'); 
      line = reader.readLine(); 
     } 
    } 
    String newText = builder.toString(); 

雖然寫入臨時文件也是一個很好的解決方案。在兩種情況下,處理速度最慢的I/O數量是相同的 - 讀取完整內容一次,寫入結果一次。

+1

注意:將'append'拆分爲2個調用,以避免在進行連接時爲每行創建一個新字符串。 –

+0

@AndyTurner:你可以舉個例子說明你的意思嗎? – tabby

+0

Andy是對的,請參閱我的回答的第二部分 – Mifeet

5

您的第一個程序很慢的主要原因可能是它建立了字符串oldtext遞增。問題在於,每次添加另一行時,都可能需要複製一行。由於每個副本的時間大致與正在複製的字符串的長度成正比,因此您的執行時間將按照輸入文件大小的平方進行縮放。

您可以通過嘗試使用不同長度的文件並查看運行時如何依賴於文件大小來檢查這是否是您的問題。

如果是這樣,一個簡單的方法來解決這個問題是Java的StringBuilder class這是專門用於完成這項任務:增量建立一個大的字符串。