我想创建一个简单的程序(使用Java语言),它可以编辑文本文件,特别是能够在文本文件的随机位置插入任意文本。该功能是我目前正在编写的一个更大程序的一部分。
阅读有关java.util.RandomAccessFile的描述,似乎在文件中间进行任何写操作都会覆盖现有内容。这是一个副作用,我希望避免(如果可能的话)。
有没有简单的方法来实现这个功能呢?
提前感谢您的帮助。
我想创建一个简单的程序(使用Java语言),它可以编辑文本文件,特别是能够在文本文件的随机位置插入任意文本。该功能是我目前正在编写的一个更大程序的一部分。
阅读有关java.util.RandomAccessFile的描述,似乎在文件中间进行任何写操作都会覆盖现有内容。这是一个副作用,我希望避免(如果可能的话)。
有没有简单的方法来实现这个功能呢?
提前感谢您的帮助。
好的,这个问题很旧了,但FileChannels自Java 1.4以来就存在了,我不知道为什么在处理替换或插入文件内容的问题时没有人提到它们。 FileChannels速度快,请使用它们。
这里是一个示例(忽略异常和其他一些东西):
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();
}
Graphic
对象而不是FileChannel
。 - Yohanim嗯,我不认为有一种方式可以通过单个标准的Java IO API调用避免覆盖现有内容。
如果文件不太大,只需将整个文件读入ArrayList(每行一个条目),然后重写条目或插入新条目以获得新行。
然后使用新内容覆盖现有文件,或将现有文件移动到备份并编写新文件。
根据所需编辑的复杂程度,您的数据结构可能需要更改。
另一种方法是从现有文件中读取字符,同时向已编辑的文件中写入并在读取时编辑流。
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);
}
我不确定除了以下方法外是否有更方便的方式:
关于目标文件:如果处理的文件不是太大,您可以在内存中构建新内容,然后覆盖旧文件的内容。或者,您可以将结果写入临时文件。
使用流可能是最容易的方法,RandomAccessFile 似乎不适用于在中间插入(据我所知)。如果需要,请查看 教程。
由于@xor_eq的编辑队列已满,在这里我提供一个新答案,它更详细并且稍微改进了他的版本:
public static void insert(String filename, long offset, byte[] content) throws IOException {
File temp = Files.createTempFile("insertTempFile", ".temp").toFile(); // Create a temporary file to save content to
try (RandomAccessFile r = new RandomAccessFile(new File(filename), "rw"); // Open file for read & write
RandomAccessFile rtemp = new RandomAccessFile(temp, "rw"); // Open temporary file for read & write
FileChannel sourceChannel = r.getChannel(); // Channel of file
FileChannel targetChannel = rtemp.getChannel()) { // Channel of temporary file
long fileSize = r.length();
sourceChannel.transferTo(offset, (fileSize - offset), targetChannel); // Copy content after insert index to
// temporary file
sourceChannel.truncate(offset); // Remove content past insert index from file
r.seek(offset); // Goto back of file (now insert index)
r.write(content); // Write new content
long newOffset = r.getFilePointer(); // The current offset
targetChannel.position(0L); // Goto start of temporary file
sourceChannel.transferFrom(targetChannel, newOffset, (fileSize - offset)); // Copy all content of temporary
// to end of file
}
Files.delete(temp.toPath()); // Delete the temporary file as not needed anymore
}