File Input Output Java

/*
 * @(#)$Id: codetemplate_xbird.xml 943 2006-09-13 07:03:37Z yui $
 *
 * Copyright 2006-2008 Makoto YUI
 *
 * Licensed 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.
 * 
 * Contributors:
 *     Makoto YUI - initial implementation
 */
//package xbird.util.io;
import java.io.IOException;
import java.io.InputStream;
/**
 * 
 * 

 * 

 * 
 * @author Makoto YUI (yuin405+xbird@gmail.com)
 */
public final class FastMultiByteArrayInputStream extends InputStream {
    private final byte[][] _buffers;
    private final int _blocksize;
    private int _pos;
    private int _count;
    private byte[] _curBlock;
    private int _curBlockIdx;
    private int _curBlockOffset;
    private boolean _cleanable = false;
    // TODO variable block size
    public FastMultiByteArrayInputStream(byte[][] buffers, int blockSize, int totalSize) {
        if(buffers == null) {
            throw new IllegalArgumentException();
        }
        this._buffers = buffers;
        this._blocksize = blockSize;
        this._pos = 0;
        this._count = totalSize;
        this._curBlock = buffers[0];
        this._curBlockIdx = 0;
        this._curBlockOffset = 0;
    }
    public void setCleanable(boolean cleanable) {
        this._cleanable = cleanable;
    }
    public int read() {
        final byte[] block = getCurBlock(_pos++);
        return (_pos < _count) ? (block[_curBlockOffset++] & 0xff) : -1;
    }
    @Override
    public int read(final byte b[], int off, int len) {
        if(b == null) {
            throw new NullPointerException();
        } else if(off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        }
        if(_pos >= _count) {
            return -1;
        }
        if(_pos + len > _count) {
            len = _count - _pos;
        }
        if(len <= 0) {
            return 0;
        }
        final int limit = _pos + len;
        for(int n = _pos; n < limit;) {
            final byte[] block = getCurBlock(n);
            final int numleft = _blocksize - _curBlockOffset;
            final int copylen = Math.min(limit - n, numleft);
            System.arraycopy(block, _curBlockOffset, b, off, copylen);
            _curBlockOffset += copylen;
            off += copylen;
            n += copylen;
        }
        _pos += len;
        return len;
    }
    private byte[] getCurBlock(final int pos) {
        if(_curBlockOffset < _blocksize) {
            return _curBlock;
        } else {
            if(_cleanable) {
                _buffers[_curBlockIdx] = null;
            }
            final int nextBlockIdx = ++_curBlockIdx;
            final byte[] block = _buffers[nextBlockIdx];
            this._curBlock = block;
            this._curBlockOffset = 0;
            return block;
        }
    }
    @Override
    public long skip(long n) {
        if(_pos + n > _count) {
            n = _count - _pos;
        }
        if(n < 0) {
            return 0;
        }
        _pos += n;
        return n;
    }
    @Override
    public int available() {
        return _count - _pos;
    }
    @Override
    public boolean markSupported() {
        return false;
    }
    @Override
    public void mark(int readAheadLimit) {
        throw new UnsupportedOperationException();
    }
    @Override
    public void reset() {
        throw new UnsupportedOperationException();
    }
    @Override
    public void close() throws IOException {}
}