All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.indeed.util.io.BufferedFileDataInputStream Maven / Gradle / Ivy

The newest version!
package com.indeed.util.io;

import com.google.common.io.Closer;
import com.google.common.io.LittleEndianDataInputStream;

import java.io.DataInput;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

/** @author jplaisance */
public final class BufferedFileDataInputStream extends InputStream implements DataInput, Seekable {
    private static final int DEFAULT_BUFFER_SIZE = 131072;

    private final Closer closer = Closer.create();

    private final FileChannel channel;

    private final ByteBuffer buffer;

    private long bufferPos;

    private final DataInput dataInput;

    public BufferedFileDataInputStream(File file) throws FileNotFoundException {
        this(file, ByteOrder.BIG_ENDIAN);
    }

    public BufferedFileDataInputStream(File file, ByteOrder order) throws FileNotFoundException {
        this(file, order, DEFAULT_BUFFER_SIZE);
    }

    public BufferedFileDataInputStream(File file, ByteOrder order, int bufferSize)
            throws FileNotFoundException {
        // for backwards compatiblity with file interface, we still use RandomAccessFile
        final RandomAccessFile raf = closer.register(new RandomAccessFile(file, "r"));
        channel = raf.getChannel();
        closer.register(channel);

        buffer = ByteBuffer.allocate(bufferSize);
        buffer.limit(0);
        if (order == ByteOrder.BIG_ENDIAN) {
            dataInput = new DataInputStream(this);
        } else {
            dataInput = new LittleEndianDataInputStream(this);
        }
    }

    public BufferedFileDataInputStream(Path path) throws IOException {
        this(path, ByteOrder.BIG_ENDIAN);
    }

    public BufferedFileDataInputStream(Path path, ByteOrder order) throws IOException {
        this(path, order, DEFAULT_BUFFER_SIZE);
    }

    public BufferedFileDataInputStream(Path path, ByteOrder order, int bufferSize)
            throws IOException {
        channel = FileChannel.open(path, StandardOpenOption.READ);
        closer.register(channel);

        buffer = ByteBuffer.allocate(bufferSize);
        buffer.limit(0);
        if (order == ByteOrder.BIG_ENDIAN) {
            dataInput = new DataInputStream(this);
        } else {
            dataInput = new LittleEndianDataInputStream(this);
        }
    }

    private boolean fillBuffer() throws IOException {
        buffer.position(0);
        int limit = (int) Math.min((channel.size() - channel.position()), buffer.capacity());
        buffer.limit(limit);
        if (limit == 0) return false;
        bufferPos = channel.position();
        channel.read(buffer);
        buffer.flip();
        return true;
    }

    @Override
    public int read() throws IOException {
        if (buffer.remaining() == 0) {
            if (!fillBuffer()) return -1;
        }
        return buffer.get() & 0xFF;
    }

    @Override
    public int read(final byte[] b, final int off, final int len) throws IOException {
        if (buffer.remaining() == 0) {
            if (!fillBuffer()) return -1;
        }
        int read = Math.min(len, buffer.remaining());
        buffer.get(b, off, read);
        return read;
    }

    public long position() throws IOException {
        return bufferPos + buffer.position();
    }

    public long length() throws IOException {
        return channel.size();
    }

    public void seek(long addr) throws IOException {
        if (addr >= bufferPos && addr <= bufferPos + buffer.limit()) {
            buffer.position((int) (addr - bufferPos));
        } else {
            channel.position(addr);
            bufferPos = addr;
            buffer.position(0);
            buffer.limit(0);
        }
    }

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

    @Override
    public String readUTF() throws IOException {
        return dataInput.readUTF();
    }

    @Override
    public String readLine() throws IOException {
        return dataInput.readLine();
    }

    @Override
    public double readDouble() throws IOException {
        return dataInput.readDouble();
    }

    @Override
    public float readFloat() throws IOException {
        return dataInput.readFloat();
    }

    @Override
    public long readLong() throws IOException {
        return dataInput.readLong();
    }

    @Override
    public int readInt() throws IOException {
        return dataInput.readInt();
    }

    @Override
    public char readChar() throws IOException {
        return dataInput.readChar();
    }

    @Override
    public int readUnsignedShort() throws IOException {
        return dataInput.readUnsignedShort();
    }

    @Override
    public short readShort() throws IOException {
        return dataInput.readShort();
    }

    @Override
    public boolean readBoolean() throws IOException {
        return dataInput.readBoolean();
    }

    @Override
    public int skipBytes(final int n) throws IOException {
        return dataInput.skipBytes(n);
    }

    @Override
    public void readFully(final byte[] b, final int off, final int len) throws IOException {
        dataInput.readFully(b, off, len);
    }

    @Override
    public void readFully(final byte[] b) throws IOException {
        dataInput.readFully(b);
    }

    @Override
    public byte readByte() throws IOException {
        return dataInput.readByte();
    }

    @Override
    public int readUnsignedByte() throws IOException {
        return dataInput.readUnsignedByte();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy