package org.archive.util.binsearch.impl; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import org.archive.util.binsearch.SeekableLineReader; public class NIOSeekableLineReader implements SeekableLineReader { private FileChannel fc; private long size; private FileChannelInputStream fcis; private InputStreamReader isr; private BufferedReader br; private int blockSize = 4096; public NIOSeekableLineReader(FileChannel fc) throws IOException { this.fc = fc; size = fc.size(); fcis = null; } public void seek(long offset) throws IOException { fcis = new FileChannelInputStream(fc, offset); isr = new InputStreamReader(fcis, UTF8); br = new BufferedReader(isr, blockSize); } public String readLine() throws IOException { if(br == null) { seek(0); } return br.readLine(); } public void close() throws IOException { // NO-OP } public long getSize() throws IOException { return size; } public class FileChannelInputStream extends InputStream { FileChannel fc; long fcOffset; public FileChannelInputStream(FileChannel fc, long offset) { this.fc = fc; this.fcOffset = offset; } @Override public int read() throws IOException { byte b[] = new byte[1]; int amt = read(b, 0, 1); if (amt == -1) { return -1; } return b[0] & 0xff; } @Override public int read(byte[] b) throws IOException { return read(b, 0, b.length); } public int read(byte[] buffer, int offset, int length) throws IOException { ByteBuffer bb = ByteBuffer.wrap(buffer,offset,length); int totalRead = 0; while(length > 0) { int amtRead = fc.read(bb, fcOffset); if(amtRead == -1) { // EOF: break; } totalRead += amtRead; fcOffset += amtRead; length -= amtRead; } return totalRead == 0 ? -1 : totalRead; } } }