Java - delete line from text file by overwriting while reading it

后端 未结 3 1861
离开以前
离开以前 2020-11-27 07:59

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 traver

相关标签:
3条回答
  • 2020-11-27 08:39

    @shelley: you can't do what you are trying to do and what's more, you shouldn't. You should read the file and write to a temporary file for several reasons, for one, it's possible to do it this way (as opposed to what you're trying to do) and for another, if the process gets corrupted, you could bale out without loss of the original file. Now you could update a specific location of a file using a RandomAccessFile, but this is usually done (in my experience) when you are dealing with fixed sized records rather than typical text files.

    0 讨论(0)
  • 2020-11-27 09:00

    You cannot do it this way. FileWriter can only append to a file, rather than write in the middle of it - You need RandomAccessFile if you want to write in the middle. What you do now - you override the file the first time you write to it (and it gets empty - that's why you get the exception). You can create FileWriter with append flag set to true - but this way you would append to a file rather than write in the middle of it.

    I'd really recommend to write to a new file and then rename it at the end.

    0 讨论(0)
  • 2020-11-27 09:02

    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:

    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();
    }
    
    0 讨论(0)
提交回复
热议问题