My file is very large, so I don't want to read and search the whole file. Is there a way in java I could search from the end of the file line by line, and then replace a certain part of it?
My file looks like this:
Line 1
Line 2
Line 3
......
Line 99995
Line 99996
abc_
Line 99998
Line 99999
and I want to replace abc_ to def_
You can do this using FileChannel and ReversedLinesFileReader.
For using reader you need to add Appache-Commons IO dependency:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
First you need to find position of your line abc_. After that you can write line def_ into your file using FileChannel and found position.
Code would be:
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);
}
Note:
FileChannel.write will rewrite bytes since position you've passed, it means you can replace abc_ only by line with the same length (def_ has same length).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With