ushumpei’s blog

生活で気になったことを随時調べて書いていきます。

Java でストリームの末尾数行を捨てる

末尾の行を捨てるためには一旦ファイルを全部読まなきゃいけないかと思ったけど、捨てたい行数を先読みしておけば良いという感じでした。

import java.io.*;
import java.util.LinkedList;
import java.util.Queue;

// ファイルの末尾数行捨てる BufferedReader
class TailIgnoringBufferedReader extends Reader {
    private final BufferedReader _reader;
    private final int num;

    Queue<String> queue = new LinkedList<>();

    TailIgnoringBufferedReader(Reader in, int num) {
        this._reader = new BufferedReader(in);
        this.num = num;
    }

    public String readLine() throws IOException {
        while (this.queue.size() <= this.num) {
            String line = this._reader.readLine();
            if (line == null) return null;
            this.queue.add(line);
        }
        return this.queue.poll();
    }

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException {
        return this._reader.read();
    }

    @Override
    public void close() throws IOException {
        this._reader.close();
    }
}

( lines とかは未実装。BufferedReader と名付けていいかは微妙なところかも。)

こんな感じで使えます

InputStream data = new ByteArrayInputStream("1\n2\n3\n4\n5\n6\n7\n8\n9".getBytes());
try (TailIgnoringBufferedReader reader = new TailIgnoringBufferedReader(new InputStreamReader(data), 5)) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}

先頭も捨てられるようにすれば任意の切り出し方ができるようになる

感想

InputStream 系のコードは書いていて楽しい

read とかでも対応するにはどうするべきなんだろうか?(先読みは同じで、 currentLine みたいなインスタンス変数持ってそこから返していく、空になったら Queue からロードする感じかな)