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

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

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

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

import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
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 BufferedFileDataOutputStream extends OutputStream implements SyncableDataOutput {
    private static final int DEFAULT_BUFFER_SIZE = 131072;

    private final ByteBuffer buffer;

    private final FileChannel channel;

    private final DataOutput dataOut;

    private final Closer closer = Closer.create();

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

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

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

        buffer = ByteBuffer.allocate(bufferSize);
        if (order == ByteOrder.LITTLE_ENDIAN) {
            dataOut = new LittleEndianDataOutputStream(this);
        } else if (order == ByteOrder.BIG_ENDIAN) {
            dataOut = new DataOutputStream(this);
        } else {
            throw new IllegalArgumentException(
                    order + " is not ByteOrder.BIG_ENDIAN or ByteOrder.LITTLE_ENDIAN");
        }
    }

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

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

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

        buffer = ByteBuffer.allocate(bufferSize);
        if (order == ByteOrder.LITTLE_ENDIAN) {
            dataOut = new LittleEndianDataOutputStream(this);
        } else if (order == ByteOrder.BIG_ENDIAN) {
            dataOut = new DataOutputStream(this);
        } else {
            throw new IllegalArgumentException(
                    order + " is not ByteOrder.BIG_ENDIAN or ByteOrder.LITTLE_ENDIAN");
        }
    }

    @Override
    public void write(final int b) throws IOException {
        if (buffer.remaining() == 0) {
            flush();
        }
        buffer.put((byte) b);
    }

    @Override
    public void write(final byte[] b, final int off, final int len) throws IOException {
        int current = off;
        final int end = off + len;
        while (current < end) {
            int size = Math.min(buffer.remaining(), end - current);
            if (size == 0) {
                flush();
                continue;
            }
            buffer.put(b, current, size);
            current += size;
        }
    }

    @Override
    public void writeBoolean(final boolean v) throws IOException {
        dataOut.writeBoolean(v);
    }

    @Override
    public void writeByte(final int v) throws IOException {
        dataOut.writeByte(v);
    }

    @Override
    public void writeShort(final int v) throws IOException {
        dataOut.writeShort(v);
    }

    @Override
    public void writeChar(final int v) throws IOException {
        dataOut.writeChar(v);
    }

    @Override
    public void writeInt(final int v) throws IOException {
        dataOut.writeInt(v);
    }

    @Override
    public void writeLong(final long v) throws IOException {
        dataOut.writeLong(v);
    }

    @Override
    public void writeFloat(final float v) throws IOException {
        dataOut.writeFloat(v);
    }

    @Override
    public void writeDouble(final double v) throws IOException {
        dataOut.writeDouble(v);
    }

    @Override
    public void writeBytes(final String s) throws IOException {
        dataOut.writeBytes(s);
    }

    @Override
    public void writeChars(final String s) throws IOException {
        dataOut.writeChars(s);
    }

    @Override
    public void writeUTF(final String str) throws IOException {
        dataOut.writeUTF(str);
    }

    @Override
    public void flush() throws IOException {
        buffer.flip();
        channel.write(buffer);
        buffer.clear();
    }

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

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

    @Override
    public void sync() throws IOException {
        flush();
        channel.force(true);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy