通过 Java 将文本插入到现有文件中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/289965/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:37:42  来源:igfitidea点击:

Inserting text into an existing file via Java

javafilefile-iofilesystems

提问by Dinuk

I would like to create a simple program (in Java) which edits text files - particularly one which performs inserting arbitrary pieces of text at random positions in a text file. This feature is part of a larger program I am currently writing.

我想创建一个简单的程序(在 Java 中)来编辑文本文件 - 特别是一个在文本文件中的随机位置插入任意文本片段的程序。此功能是我目前正在编写的更大程序的一部分。

Reading the description about java.util.RandomAccessFile, it appears that any write operations performed in the middle of a file would actually overwrite the exiting content. This is a side-effect which I would like to avoid (if possible).

阅读有关 java.util.RandomAccessFile 的描述,似乎在文件中间执行的任何写操作实际上都会覆盖现有内容。这是我想避免的副作用(如果可能的话)。

Is there a simple way to achieve this?

有没有简单的方法来实现这一目标?

Thanks in advance.

提前致谢。

采纳答案by xor_eq

Okay, this question is pretty old, but FileChannels exist since Java 1.4 and I don't know why they aren't mentioned anywhere when dealing with the problem of replacing or inserting content in files. FileChannelsare fast, use them.

好的,这个问题已经很老了,但是 FileChannels 自 Java 1.4 以来就存在,我不知道为什么在处理替换或插入文件内容的问题时没有提到它们。FileChannels很快,请使用它们。

Here's an example (ignoring exceptions and some other stuff):

这是一个示例(忽略异常和其他一些内容):

public void insert(String filename, long offset, byte[] content) {
  RandomAccessFile r = new RandomAccessFile(new File(filename), "rw");
  RandomAccessFile rtemp = new RandomAccessFile(new File(filename + "~"), "rw");
  long fileSize = r.length();
  FileChannel sourceChannel = r.getChannel();
  FileChannel targetChannel = rtemp.getChannel();
  sourceChannel.transferTo(offset, (fileSize - offset), targetChannel);
  sourceChannel.truncate(offset);
  r.seek(offset);
  r.write(content);
  long newOffset = r.getFilePointer();
  targetChannel.position(0L);
  sourceChannel.transferFrom(targetChannel, newOffset, (fileSize - offset));
  sourceChannel.close();
  targetChannel.close();
}

回答by Brendan Cashman

I believe the only way to insert text into an existing text file is to read the original file and write the content in a temporary file with the new text inserted. Then erase the original file and rename the temporary file to the original name.

我相信将文本插入现有文本文件的唯一方法是读取原始文件并将内容写入临时文件并插入新文本。然后擦除原始文件并将临时文件重命名为原始名称。

This exampleis focused on inserted a single line into an existing file, but still maybe of use to you.

这个例子的重点是在现有文件中插入一行,但仍然可能对你有用。

回答by Touko

I don't know if there's a handy way to do it straight otherwise than

我不知道是否有一种方便的方法可以直接做到这一点,而不是

  • read the beginning of the file and write it to target
  • write your new text to target
  • read the rest of the file and write it to target.
  • 读取文件的开头并将其写入目标
  • 将您的新文本写入目标
  • 读取文件的其余部分并将其写入目标。

About the target : You can construct the new contents of the file in memory and then overwrite the old content of the file if the files handled aren't so big. Or you can write the result to a temporary file.

关于目标:如果处理的文件不是那么大,您可以在内存中构造文件的新内容,然后覆盖文件的旧内容。或者您可以将结果写入临时文件。

The thing would probably be easiest to do with streams, RandomAccessFile doesn't seem to be meant for inserting in the middle (afaik). Check the tutorialif you need.

使用流可能最容易做到这一点,RandomAccessFile 似乎并不意味着插入中间(afaik)。如果需要,请查看教程

回答by Ken Gentle

Well, no, I don't believe there is a way to avoid overwriting existing content with a single, standard Java IO API call.

嗯,不,我认为没有办法避免使用单个标准 Java IO API 调用覆盖现有内容。

If the files are not too large, just read the entire file into an ArrayList (an entry per line) and either rewrite entries or insert new entries for new lines.

如果文件不是太大,只需将整个文件读入一个 ArrayList(每行一个条目),然后重写条目或为新行插入新条目。

Then overwrite the existing file with new content, or move the existing file to a backup and write a new file.

然后用新内容覆盖现有文件,或将现有文件移动到备份并写入新文件。

Depending on how sophisticated the edits need to be, your data structure may need to change.

根据编辑需要的复杂程度,您的数据结构可能需要更改。

Another method would be to read characters from the existing file while writing to the edited file and edit the stream as it is read.

另一种方法是在写入已编辑文件的同时从现有文件中读取字符,并在读取流时对其进行编辑。

回答by Zan Lynx

If Java has a way to memory map files, then what you can do is extend the file to its new length, map the file, memmove all the bytes down to the end to make a hole and write the new data into the hole.

如果 Java 有内存映射文件的方法,那么您可以做的是将文件扩展到新的长度,映射文件,将所有字节向下移动到末尾以形成一个洞并将新数据写入洞中。

This works in C. Never tried it in Java.

这适用于 C。从未在 Java 中尝试过。

Another way I just thought of to do the same but with random file access.

我刚刚想到的另一种方法是使用随机文件访问来做同样的事情。

  • Seek to the end - 1 MB
  • Read 1 MB
  • Write that to original position + gap size.
  • Repeat for each previous 1 MB working toward the beginning of the file.
  • Stop when you reach the desired gap position.
  • 寻找到最后 - 1 MB
  • 读取 1 MB
  • 将其写入原始位置 + 间隙大小。
  • 对文件开头的每个前 1 MB 重复此操作。
  • 当您到达所需的间隙位置时停止。

Use a larger buffer size for faster performance.

使用更大的缓冲区大小以获得更快的性能。

回答by Zan Lynx

If it is a text file,,,,Read the existing file in StringBuffer and append the new content in the same StringBuffer now u can write the SrtingBuffer on file. so now the file contains both the existing and new text.

如果是文本文件,,,,, 读取 StringBuffer 中的现有文件并将新内容附加到同一个 StringBuffer 中,现在您可以将 SrtingBuffer 写入文件。所以现在文件包含现有文本和新文本。

回答by S.Yavari

You can use following code:

您可以使用以下代码:

BufferedReader reader = null;
BufferedWriter writer = null;
ArrayList list = new ArrayList();

try {
    reader = new BufferedReader(new FileReader(fileName));
    String tmp;
    while ((tmp = reader.readLine()) != null)
        list.add(tmp);
    OUtil.closeReader(reader);

    list.add(0, "Start Text");
    list.add("End Text");

    writer = new BufferedWriter(new FileWriter(fileName));
    for (int i = 0; i < list.size(); i++)
        writer.write(list.get(i) + "\r\n");
} catch (Exception e) {
    e.printStackTrace();
} finally {
    OUtil.closeReader(reader);
    OUtil.closeWriter(writer);
}