Java - 在读取时通过覆盖从文本文件中删除行 [英] Java - delete line from text file by overwriting while reading it

查看:99
本文介绍了Java - 在读取时通过覆盖从文本文件中删除行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从文本文件中删除一行文本而不复制到临时文件。我试图通过使用Printwriter和扫描仪并让它们同时遍历文件来做到这一点,作者写下扫描仪读取的内容并用相同的东西覆盖每一行,直到它到达我想要的行删除。然后,我推进扫描仪而不是编写器,并继续像以前一样。这是代码:

I'm trying to delete a line of text from a text file without copying to a temporary file. I am trying to do this by using a Printwriter and a Scanner and having them traverse the file at the same time, the writer writing what the Scanner reads and overwriting each line with the same thing, until it gets to the line that I wish to delete. Then, I advance the Scanner but not the writer, and continue as before. Here is the code:

但首先,参数:我的文件名是数字,所以这将读取1.txt或2.txt等,所以f指定文件名。我将它转换为文件的构造函数中的String。 Int n是我要删除的行的索引。

But first, the parameters: My file names are numbers, so this would read 1.txt or 2.txt, etc, and so f specifies the file name. I convert it to a String in the constructor for a file. Int n is the index of the line that I want to delete.

public void deleteLine(int f, int n){
 try{
 Scanner reader = new Scanner(new File(f+".txt")); 
 PrintWriter writer = new PrintWriter(new FileWriter(new File(f+".txt")),false); 
 for(int w=0; w<n; w++)
   writer.write(reader.nextLine()); 
 reader.nextLine(); 
 while(reader.hasNextLine())
   writer.write(reader.nextLine());
 } catch(Exception e){
   System.err.println("Enjoy the stack trace!");
   e.printStackTrace();
 }
}

它给了我奇怪的错误。它在堆栈跟踪中显示NoSuchElementException和no line found。它指向不同的线;似乎任何nextLine()调用都可以做到这一点。是否可以通过这种方式删除一行?如果是这样,我做错了什么?如果没有,为什么? (顺便说一句,如果你想要这个,那么文本文件大约有500行。不过,我不知道这个数字有多大甚至很重要。)

It gives me strange errors. It says "NoSuchElementException" and "no line found" in the stack trace. It points to different lines; it seems that any of the nextLine() calls can do this. Is it possible to delete a line this way? If so, what am I doing wrong? If not, why? (BTW, just in case you'd want this, the text file is about 500 lines. I don't know if that counts as large or even matters, though.)

推荐答案

正如其他人所指出的那样,如果你的程序在中途崩溃的风险最小,你可能最好使用临时文件:

As others have pointed out, you might be better off using a temporary file, if there's a slightest risk that your program crashes mid way:

public static void removeNthLine(String f, int toRemove) throws IOException {

    File tmp = File.createTempFile("tmp", "");

    BufferedReader br = new BufferedReader(new FileReader(f));
    BufferedWriter bw = new BufferedWriter(new FileWriter(tmp));

    for (int i = 0; i < toRemove; i++)
        bw.write(String.format("%s%n", br.readLine()));

    br.readLine();

    String l;
    while (null != (l = br.readLine()))
        bw.write(String.format("%s%n", l));

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

    File oldFile = new File(f);
    if (oldFile.delete())
        tmp.renameTo(oldFile);

}

(谨防编码的粗糙处理,换行字符和异常处理。)

(Beware of the sloppy treatment of encodings, new-line characters and exception handling.)

但是,我不喜欢回答问题我不会告诉你如何,因为你不应该这样做。。 (例如,在某些其他情况下,您可能正在使用大于硬盘驱动器一半的文件!)所以这里有:

However, I don't like answering questions with "I won't tell you how, because you shouldn't do it anyway.". (In some other situation for instance, you may be working with a file that's larger than half your hard drive!) So here goes:

您需要使用 RandomAccessFile 而不是。使用此类,您可以使用相同的对象读取和写入文件:

You need to use a RandomAccessFile instead. Using this class you can both read and write to the file using the same object:

public static void removeNthLine(String f, int toRemove) throws IOException {
    RandomAccessFile raf = new RandomAccessFile(f, "rw");

    // Leave the n first lines unchanged.
    for (int i = 0; i < toRemove; i++)
        raf.readLine();

    // Shift remaining lines upwards.
    long writePos = raf.getFilePointer();
    raf.readLine();
    long readPos = raf.getFilePointer();

    byte[] buf = new byte[1024];
    int n;
    while (-1 != (n = raf.read(buf))) {
        raf.seek(writePos);
        raf.write(buf, 0, n);
        readPos += n;
        writePos += n;
        raf.seek(readPos);
    }

    raf.setLength(writePos);
    raf.close();
}

这篇关于Java - 在读取时通过覆盖从文本文件中删除行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆