2014-10-05 226 views
-1

我有一個大文件,我只需要刪除多行 有沒有辦法在不打開新文件的情況下複製整個文本?從txt文件中刪除一行java

編輯: 的主要問題是,當它在一個以上的螺紋與大TXT運行filse程序無法

+0

寫一個腳本來做到這一點,並用java調用它 – 2014-10-05 11:44:56

+0

http://stackoverflow.com/questions/1377279/find-a-line-in-a-file-and-remove-it – 2014-10-05 11:47:37

+0

我知道這個選項,即時通訊尋找一種方式來做到這一點,而不是應付整個文本(我知道行號) – JohnnyF 2014-10-05 11:51:17

回答

3

有沒有辦法做到這一點,而無需打開新文件並複製整個文本?

不,沒有。當然,沒有,如果你想要安全地

RandomAccessFile也不會真的幫你。它將允許您用相同數量的字節替換文件中的一系列字節,但這不等於刪除一行。

你可以使用英國皇家空軍是這樣的:

考慮初始狀態L1L2L3...LNL3...LN

更換L2L3...LN或者你可以在一個時間使用英國皇家空軍「滑」行一個per @ halfbit的答案。

但是:

  • 在最壞的情況下,你需要複製整個文件內容,且平均案件涉及閱讀和寫作的O(N)線的字節數。

  • 這樣做的簡單方法需要在內存中保存O(N)行。

  • 「滑動」方法需要O(N) I/O操作(即系統調用)。

  • 最重要的是:通過就地文件更新刪除行是有風險的。如果應用程序在進程中間中斷(例如,電源故障),則最終會導致文件損壞。

FWIW:這是不是在Java中本身的限制。相反,它是現代操作系統代表/模型文件的一種限制。

0

看一看Random Access Files,這樣就可以在需要的位置放置文件指針移動文本。

0

這裏是一些獨立的示例代碼,使用RandomAccessFile刪除行,沒有打開一個新文件,這似乎爲我工作。 (就地複製雖然必需的。)

public static void main(String[] args) { 
    try { 
     // prepare test file 
     String path = "/tmp/test.txt"; 
     writeTestLines(path, 999999); 

     // mode "rws": read + write synchronous 
     RandomAccessFile raf = new RandomAccessFile(path, "rws"); 

     int bufSize = 1 << 20; // 1 MiB 
     Scanner s = new Scanner(new BufferedInputStream(new FileInputStream(raf.getFD()), bufSize)); 
     PrintWriter pw = new PrintWriter(new BufferedOutputStream(new FileOutputStream(raf.getFD()), bufSize)); 
     long writeOffset = 0; 
     for (int nr = 1;; nr++) { 
      if (!s.hasNextLine()) 
       break; 
      String line = s.nextLine(); 
      if (nr != 2 && !line.contains("00")) { 
       // switch to writing: save read offset, seek write offset 
       long readOffset = raf.getFilePointer(); 
       raf.seek(writeOffset); 
       pw.println(line); 
       // switch to reading: save write offset, seek read offset 
       writeOffset = raf.getFilePointer(); 
       raf.seek(readOffset); 
      } 
     } 

     // write buffered output and truncate file 
     raf.seek(writeOffset); 
     pw.flush(); 
     raf.setLength(raf.getFilePointer()); 

     pw.close(); 
     s.close(); 
     raf.close(); 
    } catch (Exception ex) { 
     ex.printStackTrace(System.err); 
    } 
} 

public static void writeTestLines(String path, int n) throws IOException { 
    PrintWriter pw = new PrintWriter(path); 
    for (int i = 1; i <= n; i++) pw.println("line " + i); 
    pw.close(); 
} 

注意,該代碼假定由掃描儀讀取該行結束是相同的由PrintWriter的(例如不只是一個單一的在Windows換行符)製作。

請注意,上面的代碼可以優化,以不重寫任何未改變的文件頭 - 例如,通過首先跟蹤寫入偏移量然後切換到「普通」PrintWriter。