在文本文件开头写入Java

问题描述 投票:0回答:7

我需要在文本文件的开头写入一些内容。我有一个包含内容的文本文件,我想在此内容之前写一些内容。说我有;

先生下午好,今天过得怎么样?
我很好,你怎么样?
谢谢你的提问,我很好

修改后我希望是这样的:

第1页-场景59
2011 年 5 月 25 日

先生下午好,今天过得怎么样?
我很好,你怎么样?
谢谢你的提问,我很好

刚刚编好的内容:)我怎样才能像这样修改文本文件?

java file text
7个回答
27
投票

您无法真正以这种方式修改 - 文件系统通常不允许您在任意位置插入数据 - 但您可以:

  • 创建一个新文件
  • 写入前缀
  • 将旧文件中的数据复制到新文件中
  • 将旧文件移动到备份位置
  • 将新文件移动到旧文件的位置
  • 可选择删除旧的备份文件

17
投票

以防万一,这里对某人有用的是使用 Apache Commons IO 库将行添加到文件的方法的完整源代码。该代码不会将整个文件读入内存,因此适用于任何大小的文件。

public static void prependPrefix(File input, String prefix) throws IOException {
    LineIterator li = FileUtils.lineIterator(input);
    File tempFile = File.createTempFile("prependPrefix", ".tmp");
    BufferedWriter w = new BufferedWriter(new FileWriter(tempFile));
    try {
        w.write(prefix);
        while (li.hasNext()) {
            w.write(li.next());
            w.write("\n");
        }
    } finally {
        IOUtils.closeQuietly(w);
        LineIterator.closeQuietly(li);
    }
    FileUtils.deleteQuietly(input);
    FileUtils.moveFile(tempFile, input);
}

3
投票

我认为你想要的是随机访问。 查看相关的java教程。 但是,我不相信您可以在文件中的任意点插入数据;如果我没记错的话,你只会覆盖数据。 如果你想插入,你必须有你的代码

  1. 复制一个块,
  2. 用你的新东西覆盖,
  3. 复制下一个块,
  4. 用之前复制的块覆盖,
  5. 返回到3,直到没有更多的块

2
投票

正如 @atk 所建议的,

java.nio.channels.SeekableByteChannel
是一个很好的界面。但仅从 1.7 开始可用。

更新:如果您使用 FileUtils 没有问题,则使用

String fileString = FileUtils.readFileToString(file);

1
投票

这不是问题的直接答案,但文件通常是通过输入流访问的。如果这是您的用例,那么您可以通过

SequenceInputStream
链接输入流以实现相同的结果。例如

InputStream inputStream = new SequenceInputStream(new ByteArrayInputStream("my line\n".getBytes()), new FileInputStream(new File("myfile.txt")));

0
投票

我会把它留在这里,以防万一有人需要

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    try (FileInputStream fileInputStream1 = new FileInputStream(fileName1);
         FileInputStream fileInputStream2 = new FileInputStream(fileName2)) {

        while (fileInputStream2.available() > 0) {
            byteArrayOutputStream.write(fileInputStream2.read());
        }
        while (fileInputStream1.available() > 0) {
            byteArrayOutputStream.write(fileInputStream1.read());
        }
    }
    try (FileOutputStream fileOutputStream = new FileOutputStream(fileName1)) {
        byteArrayOutputStream.writeTo(fileOutputStream);
    }

0
投票

阅读atk的答案后,我想出了自己的实现:

/** Prepends the provided data to the very beginning of the file.<br>
 * This functions works by overwriting the contents of the file block-by-block, first inserting the new data at the start, then
 * proceeding to shift each block down until it reaches the end of the file, at which point the last 'previous' block is written.<br>
 * <br>
 * Note that while prepending large files will not take up any extra storage space or memory, the operation will take longer to
 * complete, as it is necessary to re-write the entire file's contents once the operation has begun.
 *
 * @param data The data to prepend
 * @param off The offset within the data to read from
 * @param len The number of bytes to read within the data array
 * @param file The file to prepend the data onto
 * @throws IOException If an I/O error occurs while reading or writing to the file
 * @author Brian_Entei */
public static final void prependBytes(byte[] data, int off, int len, File file) throws IOException {
    // Insert-and-overwrite algorithm
    
    // Could potentially optimize by setting a fixed buffer length (e.g. 4096), but will then need to update/manage how many bytes are read from the stream
    final byte[] oldBuf = new byte[len];
    final byte[] buf = new byte[oldBuf.length];
    
    // Pre-load our prefix data into oldBuf
    System.arraycopy(data, off, oldBuf, 0, len);
    try(RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
        long pos = raf.getFilePointer();// store current file pointer (index into file, should be zero)
        int length, oldLength = oldBuf.length;
        while((length = raf.read(buf)) != -1) {// Let's read the first buffer (or 'block') of data
            raf.seek(pos);// since we've just read from the stream and the pointer has been changed, roll it back so that we can overwrite what we just read
            raf.write(oldBuf, 0, oldLength);// write the previously read data in the current data's place
            oldLength = length;// store the currently read data's length ...
            System.arraycopy(buf, 0, oldBuf, 0, length);// ... and data for the next loop iteration ...
            pos = raf.getFilePointer();// ... as well as the pointer (since we've just read from the stream, thus advancing the index)
        }
        raf.write(oldBuf, 0, oldLength);// (don't forget to write the last bit of data once finished!)
    }
}

/** Prepends the provided data to the very beginning of the file.<br>
 * This functions works by overwriting the contents of the file block-by-block, first inserting the new data at the start, then
 * proceeding to shift each block down until it reaches the end of the file, at which point the last 'previous' block is written.<br>
 * <br>
 * Note that while prepending large files will not take up any extra storage space or memory, the operation will take longer to
 * complete, as it is necessary to re-write the entire file's contents once the operation has begun.
 *
 * @param data The data to prepend
 * @param file The file to prepend the data onto
 * @throws IOException If an I/O error occurs while reading or writing to the file
 * @author Brian_Entei */
public static final void prependBytes(byte[] data, File file) throws IOException {
    prependBytes(data, 0, data.length, file);
}

/** Example usage of {@linkplain #prependBytes(byte[], File)}.<br>
 * <br>
 * This method inserts the UTF-8 BOM into the start of the target file.
 * 
 * @param file The text file
 * @throws IOException If an I/O error occurs while reading or writing to the file */
public static final void insertUTF8BOM(File file) throws IOException {
    prependBytes(new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF}, file);
}

此方法不会创建任何临时文件或占用大量内存,但会执行大量读取和写入操作。 事情可能可以进一步优化,但它对我来说已经足够好了。

© www.soinside.com 2019 - 2024. All rights reserved.