I have a .txt
file, which I want to process in Java. I want to delete its last line.
I need ideas on how to achieve this without having to copy the entire content into another file and ignoring the last line. Any suggestions?
In Java, we can use the Apache Commons IO ReversedLinesFileReader to read the last few lines of a File .
You could find the beginning of the last line by scanning the file and then truncate it using FileChannel.truncate
or RandomAccessFile.setLength
.
By taking RandomAccessFile you can:
Code would be something like this:
LinkedList<String> lines=null;
int howMuch = 1; // one line to read and delete
try{
RandomAccessFile raf = new RandomAccessFile(inputFileName, "rw");
System.out.println("File Length="+raf.length());
long step = 20; // here I advice to write average length of line
long jump = raf.length()<step*howMuch?
0:
raf.length()-step*howMuch;
raf.seek(jump);
lines = new LinkedList<String>();
LinkedList<Long> pos = new LinkedList<Long>();
Entry<LinkedList<String>,LinkedList<Long>> rLinesRead = getRemainingLines(raf,
new AbstractMap.SimpleEntry<LinkedList<String>,LinkedList<Long>> (lines,pos));
while(rLinesRead.getKey().size()<howMuch){
if(jump<step)
if(jump<=0)
break;
else{
jump=0;
raf.seek(jump);
rLinesRead=getRemainingLines(raf,rLinesRead);
break;
}
else
jump=jump-step;
raf.seek(jump);
rLinesRead=getRemainingLines(raf,rLinesRead);
}
int originalSize=rLinesRead.getKey().size();
lines=rLinesRead.getKey();
pos=rLinesRead.getValue();
for (int i=0;i<originalSize-howMuch;++i){
lines.removeFirst();
pos.removeFirst();
}
if(!pos.isEmpty())
raf.setLength(pos.getFirst()); // before last(from EOF) returned fully read lines in file
}catch(Exception ex){
ex.printStackTrace();
} finally{
try { raf.close(); } catch (Exception e) { e.printStackTrace(); }
}
//returns line to EOF with their begin file pointer positions
private Entry<LinkedList<String>,LinkedList<Long>> getRemainingLines(RandomAccessFile raf,
Entry<LinkedList<String>,LinkedList<Long>> linesAlreadyLoadedFromEnd) throws IOException{
LinkedList<String> pLines = linesAlreadyLoadedFromEnd.getKey();
LinkedList<Long> pPos = linesAlreadyLoadedFromEnd.getValue();
long init=raf.getFilePointer();
String str = raf.readLine();
if(pPos.size()>0?pPos.getFirst()==0:false || str==null)
return linesAlreadyLoadedFromEnd;
LinkedList<String> lines = new LinkedList<String>();
LinkedList<Long> pos = new LinkedList<Long>();
if(init==0L ){
lines.add(str);
pos.add(0L);
}
Long tmpPos = raf.getFilePointer();
while ((str = raf.readLine())!=null && !pPos.contains(tmpPos)){
lines.add(str);
pos.add(tmpPos);
tmpPos = raf.getFilePointer();
}
pLines.addAll(0,lines);
pPos.addAll(0,pos);
return new AbstractMap.SimpleEntry<LinkedList<String>,LinkedList<Long>> (pLines,pPos);
}
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