2014-10-05 165 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。