在Java中向文本文件开头写入内容。

13

我需要在文本文件开头写入一些内容。我有一个包含内容的文本文件,并且想要在这个内容之前写入一些东西。比如我有:

下午好先生,您今天过得怎么样?
我很好,你呢?
谢谢关心,我很棒

修改后,我希望它变成这样:

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

下午好先生,您今天过得怎么样?
我很好,你呢?
谢谢关心,我很棒

只是编造的内容 :) 如何将文本文件修改为这种方式?


@Turuko 首先,您必须确定分隔符。没有分隔符(无论是显式还是隐式的),您都无法实现目标。通过问自己这个问题更容易理解:“我如何知道何时在对话框上方插入页面和场景标题?”如果您没有办法确定文本文件中的位置,则无法完成此操作。 - Matthew Cox
2
@Matthew:我在这里没有看到问题——它只是在文本文件的开头写入一段固定的文本。至少就问题所提出的内容而言,无需识别任何内容。 - Jon Skeet
@Jon 或许我误解了这个问题。我理解这个问题是在问:“我有这个文本文件,如何修改它以在整个文件的某些部分之间添加元数据”。 - Matthew Cox
@Jon 和 @Turuko 如果你只是想在文件开头插入这个头部信息,那么可以忽略我的评论。=P - Matthew Cox
请参见 https://dev59.com/sHRA5IYBdhLWcg3wzhNY?lq=1 - Raedwald
6个回答

27

你不能以这种方式真正进行修改 - 文件系统通常不允许您在任意位置插入数据 - 但您可以做以下操作:

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

这看起来是我问题可行的解决方案。感谢您的回答,非常感激。我会立即开始着手处理。 - toruko
这个过程是否是巨大的资源浪费?我正在寻找一种成本效益高的实现。 - Poutrathor
@Poutrathor:你所说的“成本效益”具体指什么?(只有在低效率会带来实际成本的情况下,“成本效益”才等同于“高效”)。基本上,如果你想要能够执行随机插入/删除操作,你可能不想将其存储为纯文本文件... - Jon Skeet
1
@JonSkeet 对不起,我的英语不是很好。我在一台硬件受限的设备上工作(该设备并不那么强大)。因此,我应该尽量实现对CPU和RAM负载较小的解决方案。文件操作可能会很重,特别是如果我需要复制文件。背景:我想以倒序时间显示我的日志:最新的日志先显示。我只看到两种方法:将最新的日志写在文件顶部,从底部向上读取文件。我不知道哪个更好。由于这是一个开放性问题,我也不知道在哪里提问,所以我正在浏览SO答案,以便自己找到答案 :) - Poutrathor
1
@Poutrathor:在这种情况下,我肯定会实现文件倒序读取...可能将文件分成块(例如每小时一个新的日志文件),以使它更简单。 - Jon Skeet
@JonSkeet 感谢您的建议!对我来说,插入似乎也很耗费时间。<抱怨>2015年文件操作如此糟糕,真是难以置信</抱怨> - Poutrathor

16

如果有人需要,这里是使用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);
}

2
我认为你想要的是随机访问。请查看相关的Java教程。然而,我不认为你可以在文件的任意位置插入数据;如果我没记错的话,你只能覆盖数据。如果你想要插入,你需要让你的代码:
  1. 复制一个块,
  2. 用你的新内容覆盖,
  3. 复制下一个块,
  4. 用之前复制的块覆盖,
  5. 回到步骤3直到没有更多的块。

1
随机访问通常允许您在任意点上覆盖数据 - 而不是在文件中插入数据。 - Jon Skeet
Jon,是的,当你在评论时,我正在编辑我的回复 :) - atk

2

正如@atk所建议的,java.nio.channels.SeekableByteChannel是一个很好的接口。但它只在1.7及以上版本中可用。

更新:如果您不介意使用FileUtils,则可以使用。

String fileString = FileUtils.readFileToString(file);

1

这不是对问题的直接回答,但通常文件是通过InputStreams访问的。如果这是您的用例,则可以通过{{link1: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);
    }

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接