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

hivemall.utils.io.FastMultiByteArrayOutputStream Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package hivemall.utils.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.LinkedList;

/**
 * ByteArrayOutputStream implementation that doesn't synchronize methods.
 */
public final class FastMultiByteArrayOutputStream extends OutputStream {
    private static final int DEFAULT_BLOCK_SIZE = 8192;

    private final int blockSize;

    private byte[] buffer;
    private int size;

    private LinkedList buffers;
    private int index;

    public FastMultiByteArrayOutputStream() {
        this(DEFAULT_BLOCK_SIZE);
    }

    public FastMultiByteArrayOutputStream(int aSize) {
        this.blockSize = aSize;
        this.buffer = new byte[aSize];
    }

    public int size() {
        return size + index;
    }

    public byte[][] toMultiByteArray() {
        if (buffers == null) {
            final byte[][] mb = new byte[1][];
            mb[0] = buffer;
            return mb;
        }
        final int listsize = buffers.size();
        final int size = listsize + 1;
        final byte[][] mb = new byte[size][];
        buffers.toArray(mb);
        mb[listsize] = buffer;
        return mb;
    }

    public byte[] toByteArray() {
        final byte[] data = new byte[size()];
        // check if we have a list of buffers
        int pos = 0;
        if (buffers != null) {
            for (byte[] bytes : buffers) {
                System.arraycopy(bytes, 0, data, pos, blockSize);
                pos += blockSize;
            }
        }
        // write the internal buffer directly
        System.arraycopy(buffer, 0, data, pos, index);
        return data;
    }

    public byte[] toByteArray_clear() {
        final int size = size();
        final byte[] data = new byte[size];
        // check if we have a list of buffers
        int pos = 0;
        if (buffers != null) {
            while (!buffers.isEmpty()) {
                byte[] bytes = buffers.removeFirst();
                System.arraycopy(bytes, 0, data, pos, blockSize);
                pos += blockSize;
            }
        }
        // write the internal buffer directly
        System.arraycopy(buffer, 0, data, pos, index);
        return data;
    }

    @Override
    public String toString() {
        return new String(toByteArray());
    }

    public String toString(String enc) throws UnsupportedEncodingException {
        return new String(toByteArray(), enc);
    }

    @Override
    public void write(int datum) {
        if (index >= blockSize) {
            // Create new buffer and store current in linked list
            addBuffer();
        }
        // store the byte
        buffer[index++] = (byte) datum;
    }

    @Override
    public void write(byte[] data, int offset, int length) {
        if (data == null) {
            throw new NullPointerException();
        } else if ((offset < 0) || (offset + length > data.length) || (length < 0)) {
            throw new IndexOutOfBoundsException();
        } else {
            if (index + length >= blockSize) {// Write byte by byte
                int copyLength;
                do {
                    if (index == blockSize) {
                        addBuffer();
                    }
                    copyLength = blockSize - index;
                    if (length < copyLength) {
                        copyLength = length;
                    }
                    System.arraycopy(data, offset, buffer, index, copyLength);
                    offset += copyLength;
                    index += copyLength;
                    length -= copyLength;
                } while (length > 0);
            } else {// copy in the subarray
                System.arraycopy(data, offset, buffer, index, length);
                index += length;
            }
        }
    }

    public void writeInt(int v) throws IOException {
        if ((index + 3) >= blockSize) {
            // Create new buffer and store current in linked list
            addBuffer();
        }
        buffer[index++] = (byte) (v >>> 24);
        buffer[index++] = (byte) (v >>> 16);
        buffer[index++] = (byte) (v >>> 8);
        buffer[index++] = (byte) (v >>> 0);
    }

    public void writeLong(long v) throws IOException {
        if ((index + 7) >= blockSize) {
            // Create new buffer and store current in linked list
            addBuffer();
        }
        buffer[index++] = (byte) (v >>> 56);
        buffer[index++] = (byte) (v >>> 48);
        buffer[index++] = (byte) (v >>> 40);
        buffer[index++] = (byte) (v >>> 32);
        buffer[index++] = (byte) (v >>> 24);
        buffer[index++] = (byte) (v >>> 16);
        buffer[index++] = (byte) (v >>> 8);
        buffer[index++] = (byte) (v >>> 0);
    }

    public void writeInts(int[] v, int off, int len) throws IOException {
        int endoff = off + len;
        for (int i = off; i < endoff; i++) {
            writeInt(v[i]);
        }
    }

    public void writeLongs(long[] v, int off, int len) throws IOException {
        int endoff = off + len;
        for (int i = off; i < endoff; i++) {
            writeLong(v[i]);
        }
    }

    public void reset() {
        buffer = new byte[blockSize];
        buffers = null;
        size = 0;
        index = 0;
    }

    public void writeTo(OutputStream out) throws IOException {
        // check if we have a list of buffers
        if (buffers != null) {
            for (byte[] bytes : buffers) {
                out.write(bytes, 0, blockSize);
            }
        }
        // write the internal buffer directly
        out.write(buffer, 0, index);
    }

    public InputStream getInputStream() {
        return new FastByteArrayInputStream(toByteArray());
    }

    /**
     * Create a new buffer and store the current one in linked list.
     */
    private void addBuffer() {
        if (buffers == null) {
            buffers = new LinkedList();
        }
        buffers.addLast(buffer);
        buffer = new byte[blockSize];
        size += index;
        index = 0;
    }

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

    public void clear() {
        this.buffer = null;
        this.buffers = null;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy