Удаление последней строки файла с помощью Java
У меня есть .txt
файл, который я хочу обработать на Java. Я хочу удалить последнюю строку.
Мне нужны идеи о том, как достичь этого, не копируя весь контент в другой файл и игнорируя последнюю строку. Есть предложения?
2 ответов
вы можете найти начало последней строки, сканируя файл, а затем усечь его с помощью FileChannel.truncate
или RandomAccessFile.setLength
.
взяв RandomAccessFile вы можете:
- способ применения искать(долго) прыгать вперед и читать эти строки. Но вы не будете точно знать, насколько большим должен быть прыжок.
- чтобы удалить последние строки, вам нужно положение начала последней строки, поэтому перед чтением каждой строки сохраните их положение указателя файла (метод getFilePointer()). Удаление в ту позицию, которую вы используете setLength (длинный).
код будет что-то вроде этого:--2-->
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);
}