Here is some standalone example code using RandomAccessFile
to remove lines without opening a new file, which seems to work for me. (In-place copying is required though.)
public static void main(String[] args) {
try {
// prepare test file
String path = "/tmp/test.txt";
writeTestLines(path, 999999);
// mode "rws": read + write synchronous
RandomAccessFile raf = new RandomAccessFile(path, "rws");
int bufSize = 1 << 20; // 1 MiB
Scanner s = new Scanner(new BufferedInputStream(new FileInputStream(raf.getFD()), bufSize));
PrintWriter pw = new PrintWriter(new BufferedOutputStream(new FileOutputStream(raf.getFD()), bufSize));
long writeOffset = 0;
for (int nr = 1;; nr++) {
if (!s.hasNextLine())
break;
String line = s.nextLine();
if (nr != 2 && !line.contains("00")) {
// switch to writing: save read offset, seek write offset
long readOffset = raf.getFilePointer();
raf.seek(writeOffset);
pw.println(line);
// switch to reading: save write offset, seek read offset
writeOffset = raf.getFilePointer();
raf.seek(readOffset);
}
}
// write buffered output and truncate file
raf.seek(writeOffset);
pw.flush();
raf.setLength(raf.getFilePointer());
pw.close();
s.close();
raf.close();
} catch (Exception ex) {
ex.printStackTrace(System.err);
}
}
public static void writeTestLines(String path, int n) throws IOException {
PrintWriter pw = new PrintWriter(path);
for (int i = 1; i <= n; i++) pw.println("line " + i);
pw.close();
}
Note that this code assumes that line endings read by the Scanner are the same as produced by PrintWriter (e.g. not just a single LineFeed on Windows).
Note that above code could be optimized to not rewrite any unchanged file head - e.g. by just tracking the write offset first and then switching to a "normal" PrintWriter.