Prepend lines to file in Java

2019-01-12 02:11发布

Is there a way to prepend a line to the File in Java, without creating a temporary file, and writing the needed content to it?

标签: java file-io
6条回答
再贱就再见
2楼-- · 2019-01-12 02:51

It would be possible to do so by reading a chunk of the file of equal length to what you want to prepend, writing the new content in place of it, reading the later chunk and replacing it with what you read before, and so on, rippling down the to the end of the file.

However, don't do that, because if anything stops (out-of-memory, power outage, rogue thread calling System.exit) in the middle of that process, data will be lost. Use the temporary file instead.

查看更多
仙女界的扛把子
3楼-- · 2019-01-12 02:53
private static void addPreAppnedText(File fileName) {
    FileOutputStream fileOutputStream =null;

    BufferedReader br = null;
    FileReader fr = null;
    String newFileName = fileName.getAbsolutePath() + "@";

    try {
        fileOutputStream = new FileOutputStream(newFileName);
        fileOutputStream.write("preappendTextDataHere".getBytes());

        fr = new FileReader(fileName);
        br = new BufferedReader(fr);

        String sCurrentLine;

        while ((sCurrentLine = br.readLine()) != null) {
            fileOutputStream.write(("\n"+sCurrentLine).getBytes());

        }
        fileOutputStream.flush();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fileOutputStream.close();
            if (br != null)
                br.close();

            if (fr != null)
                fr.close();

            new File(newFileName).renameTo(new File(newFileName.replace("@", "")));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}
查看更多
神经病院院长
4楼-- · 2019-01-12 02:58

No. There are no "intra-file shift" operations, only read and write of discrete sizes.

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-01-12 03:00

There is a way, it involves rewriting the whole file though (but no temporary file). As others mentioned, no file system supports prepending content to a file. Here is some sample code that uses a RandomAccessFile to write and read content while keeping some content buffered in memory:

public static void main(final String args[]) throws Exception {
    File f = File.createTempFile(Main.class.getName(), "tmp");
    f.deleteOnExit();

    System.out.println(f.getPath());

    // put some dummy content into our file
    BufferedWriter w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
    for (int i = 0; i < 1000; i++) {
        w.write(UUID.randomUUID().toString());
        w.write('\n');
    }
    w.flush();
    w.close();

            // append "some uuids" to our file
    int bufLength = 4096;
    byte[] appendBuf = "some uuids\n".getBytes();
    byte[] writeBuf = appendBuf;
    byte[] readBuf = new byte[bufLength];

    int writeBytes = writeBuf.length;

    RandomAccessFile rw = new RandomAccessFile(f, "rw");
    int read = 0;
    int write = 0;

    while (true) {
                    // seek to read position and read content into read buffer
        rw.seek(read);
        int bytesRead = rw.read(readBuf, 0, readBuf.length);

                    // seek to write position and write content from write buffer
        rw.seek(write);
        rw.write(writeBuf, 0, writeBytes);

                    // no bytes read - end of file reached
        if (bytesRead < 0) {
                            // end of
            break;
        }

                    // update seek positions for write and read
        read += bytesRead;
        write += writeBytes;
        writeBytes = bytesRead;

                    // reuse buffer, create new one to replace (short) append buf
        byte[] nextWrite = writeBuf == appendBuf ? new byte[bufLength] : writeBuf;
        writeBuf = readBuf;
        readBuf = nextWrite;
    };

    rw.close();

            // now show the content of our file
    BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f)));

    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
}
查看更多
家丑人穷心不美
6楼-- · 2019-01-12 03:04

You could store the file content in a String and prepend the desired line by using a StringBuilder-Object. You just have to put the desired line first and then append the file-content-String.
No extra temporary file needed.

查看更多
等我变得足够好
7楼-- · 2019-01-12 03:11

No, there is no way to do that SAFELY in Java.

No filesystem implementation in any mainstream operating system supports this kind of thing, and you won't find this feature supported in any mainstream programming languages.

Real world file systems are implemented on devices that store data as fixed sized "blocks". It is not possible to implement a file system model where you can insert bytes into the middle of a file without significantly slowing down file I/O, wasting disk space or both.


The solutions that involve an in-place rewrite of the file are inherently unsafe. If your application is killed or the power dies in the middle of the prepend / rewrite process, you are likely to lose data. I would NOT recommend using that approach in practice.

Use a temporary file. It is safer.

查看更多
登录 后发表回答