Удаление последней строки файла с помощью Java - PullRequest
8 голосов
/ 05 февраля 2012

У меня есть файл .txt, который я хочу обработать на Java. Я хочу удалить его последнюю строку.

Мне нужны идеи о том, как этого добиться, не копируя весь контент в другой файл и игнорируя последнюю строку. Есть предложения?

Ответы [ 2 ]

9 голосов
/ 05 февраля 2012

Вы можете найти начало последней строки, отсканировав файл, а затем обрезать его, используя FileChannel.truncate или RandomAccessFile.setLength.

1 голос
/ 03 октября 2012

Взяв RandomAccessFile, вы можете:

  • использовать метод seek (long) , чтобы перейти вперед и прочитать эти строки.Но вы не будете точно знать, насколько большим должен быть скачок.
  • , чтобы удалить последние строки, вам нужна позиция начала последней строки, поэтому перед чтением каждой строки сохраните позицию указателя файла (метод getFilePointer () ).Для удаления на эту позицию вы используете setLength (long) .

Код будет выглядеть примерно так:

    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);
}
...