如何在Java中替换大文件末尾的字符串?

3

我的文件非常大,因此我不想读取和搜索整个文件。在Java中有没有一种方式可以从文件末尾逐行搜索,然后替换其中某一部分内容?

我的文件看起来像这样:

Line 1
Line 2
Line 3
......
Line 99995
Line 99996
abc_
Line 99998
Line 99999

我想将abc_替换为def_


我尝试从头开始阅读和搜索,对于一个文件来说需要大约50分钟的时间。 - sxy
1
看一下 RandomAccessFile。向后搜索。顺便问一下,“非常大”是多大? - g00se
2
请发布代码,50分钟的运行时间对于这种工作来说太长了。 - f1sh
你的“大”文件有多大? - Basil Bourque
1个回答

1
你可以使用FileChannelReversedLinesFileReader来完成这个操作。如果要使用reader,你需要添加Appache-Commons IO依赖。
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

首先,您需要找到您的行 abc_ 的位置。然后,您可以使用 FileChannel 和找到的 position 将行 def_ 写入文件中。

代码如下:

import org.apache.commons.io.input.ReversedLinesFileReader;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.util.Collection;

import static java.nio.file.StandardOpenOption.READ;
import static java.nio.file.StandardOpenOption.WRITE;

String path = "path/to/your/file";
String seekingLine = "abc_";
// be careful, if replacing line is bigger 
// than seekingLine it will replace symbols after seekingLine
String replacingLine = "def_";
// finding position to replace
int seekingLinePosition = 0;
File file = new File(path);
try (ReversedLinesFileReader reader = new ReversedLinesFileReader(file)) {
    String line;
    while ((line = reader.readLine()) != null && !line.equals(seekingLine)) {
        // + 1 because of line doesn't content line ending character
        seekingLinePosition = seekingLinePosition + line.getBytes().length + 1;
    }
}
// count seekingLine bytes for shifting
seekingLinePosition = seekingLinePosition + seekingLine.getBytes().length + 1;
// replace bytes by position
try (FileChannel fc = FileChannel.open(Paths.get(path), WRITE, READ)) {
    // shift to the start of seekingLine and write replacingLine bytes
    // +1 is because of uncounted seekingLine line ending char
    ByteBuffer replacingBytes = ByteBuffer.wrap(replacingLine.getBytes());
    fc.write(replacingBytes, fc.size() - seekingLinePosition + 1);
}

注意: FileChannel.write 方法将会从你传入的 position 开始重写字节,这意味着你只能用相同长度的行(例如 def_abc_ 长度相同)来替换 abc_

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