package mwt.wow.mpq; import java.io.IOException; import java.io.RandomAccessFile; class FileReader extends Reader { private final RandomAccessFile file; private static final int defaultBufferLength = 8 * 1024; private long bufferStartPosition; private int bufferDataLength; private int bufferLength; private byte[] buffer; private long readerPosition; public FileReader(RandomAccessFile file) throws IOException { this.file = file; readerPosition = file.getFilePointer(); } public FileReader(RandomAccessFile file, long position) throws IOException { this.file = file; readerPosition = position; file.seek(position); } @Override protected int readByte() throws IOException { if (buffer == null) { startBuffer(); } if (readerPosition < bufferStartPosition) { readBuffer(); } if (readerPosition >= bufferStartPosition + bufferDataLength) { if (readerPosition >= file.length()) { return -1; } readBuffer(); } int bufferIndex = (int) (readerPosition - bufferStartPosition); int b = buffer[bufferIndex]; readerPosition++; return b & 0xff; } @Override public int readBlock(byte[] b, int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } if (buffer == null) { startBuffer(); } if (readerPosition < bufferStartPosition) { readBuffer(); } int bytesRead = 0; while (bytesRead < len) { if (readerPosition >= bufferStartPosition + bufferDataLength) { if (readerPosition >= file.length()) { return bytesRead == 0 ? -1 : bytesRead; } readBuffer(); } int bufferIndex = (int) (readerPosition - bufferStartPosition); int bytesAvailable = bufferDataLength - bufferIndex; int remaining = len - bytesRead; int toRead = bytesAvailable < remaining ? bytesAvailable : remaining; System.arraycopy(buffer, bufferIndex, b, off + bytesRead, toRead); readerPosition += toRead; bytesRead += toRead; } return bytesRead; } private void startBuffer() throws IOException { bufferLength = defaultBufferLength; buffer = new byte[bufferLength]; readBuffer(); } private void readBuffer() throws IOException { bufferStartPosition = readerPosition; file.seek(bufferStartPosition); bufferDataLength = file.read(buffer); } @Override public void seek(long position) throws IOException { readerPosition = position; } }