Package com.bbn.openmap.io

Source Code of com.bbn.openmap.io.BinaryBufferedFile

// **********************************************************************
//
// <copyright>
//
//  BBN Technologies
//  10 Moulton Street
//  Cambridge, MA 02138
//  (617) 873-8000
//
//  Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/io/BinaryBufferedFile.java,v $
// $RCSfile: BinaryBufferedFile.java,v $
// $Revision: 1.2.2.4 $
// $Date: 2008/02/25 23:13:13 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap.io;

import com.bbn.openmap.MoreMath;

import java.io.EOFException;
import java.io.File;
import java.io.IOException;

/**
* This class extends the BinaryFile class, doing buffered reads on the
* underlying input file. The buffer size is not modifiable after construction,
* and the buffer management isn't the greatest.
*/
public class BinaryBufferedFile extends BinaryFile {
    /** Where reads get buffered */
    private byte buffer[];
    /** Where current reads will come from */
    private int curptr = 0;
    /** how many valid bytes are in the buffer */
    private int bytesinbuffer = 0;
    /** the byte offset of the first byte in the buffer */
    private long firstbyteoffset = 0;

    /**
     * Constructs a BinaryBufferedFile with a File and a buffer size
     *
     * @param f the input file
     * @param buffersize the size to use for buffering reads
     * @exception IOException pass-through errors from opening a BinaryFile with
     *            f
     * @see com.bbn.openmap.io.BinaryFile
     */
    public BinaryBufferedFile(File f, int buffersize) throws IOException {
        super(f);
        buffer = new byte[buffersize];
    }

    /**
     * Constructs a BinaryBufferedFile with a File
     *
     * @param f the input file
     * @exception IOException pass-through errors from opening a BinaryFile with
     *            f
     * @see com.bbn.openmap.io.BinaryFile
     */
    public BinaryBufferedFile(File f) throws IOException {
        this(f, 4096);
    }

    /**
     * Constructs a BinaryBufferedFile with a filename and a buffersize
     *
     * @param name the name/path of the input file
     * @param buffersize the size to use for buffering reads
     * @exception IOException pass-through errors from opening a BinaryFile with
     *            f
     * @see com.bbn.openmap.io.BinaryFile
     */
    public BinaryBufferedFile(String name, int buffersize) throws IOException {
        super(name);
        buffer = new byte[buffersize];
    }

    /**
     * Constructs a BinaryBufferedFile with a filename
     *
     * @param name the name/path of the input file
     * @exception IOException pass-through errors from opening a BinaryFile with
     *            f
     * @see com.bbn.openmap.io.BinaryFile
     */
    public BinaryBufferedFile(String name) throws IOException {
        this(name, 4096);
    }

    /**
     * A simple factory method that lets you try to create something without
     * having to really deal with failure. Returns a BinaryFile if successful,
     * null if not.
     */
    public static BinaryBufferedFile create(String name) {
        return create(name, 4096);
    }

    /**
     * A simple factory method that lets you try to create something without
     * having to really deal with failure. Returns a BinaryFile if successful,
     * null if not.
     */
    public static BinaryBufferedFile create(String name, int buffersize) {
        BinaryBufferedFile bf = null;
        try {
            bf = new BinaryBufferedFile(name, buffersize);
        } catch (IOException ioe) {
        }
        return bf;
    }

    /**
     * Set the input reader used by the BinaryFile. Make sure it's intialized
     * properly. Assumes that the pointer is at the beginning of the file.
     */
    public void setInputReader(InputReader reader) {
        super.setInputReader(reader);
        firstbyteoffset = 0;
        bytesinbuffer = 0;
        curptr = 0;
    }

    /**
     * Throws away whatever data is in the buffer, and refills it.
     *
     * @exception IOException IO errors encountered while refilling the buffer
     * @exception EOFException no data was left in the file
     */
    private void refillBuffer() throws IOException, EOFException {
        firstbyteoffset += (curptr + bytesinbuffer);
        int err = super.read(buffer, 0, buffer.length);
        curptr = 0;
        if (err == -1)
            throw new EOFException();
        bytesinbuffer = err;
    }

    /**
     * Forces the buffer to have at least some minimum number of bytes in it.
     *
     * @param minlength the minimum number of bytes to have in the buffer
     * @exception FormatException couldn't get enough bytes (or IO Exception)
     * @exception EOFException couldn't get any bytes
     */
    private void assertSize(int minlength) throws FormatException, EOFException {
        try {
            if (bytesinbuffer < minlength) {
                if (curptr != 0) {
                    firstbyteoffset += curptr;
                    System.arraycopy(buffer, curptr, buffer, 0, bytesinbuffer);
                    curptr = 0;
                }
                int err = super.read(buffer, bytesinbuffer, buffer.length
                        - bytesinbuffer);
                if (err == -1) {

                    if (available() <= 0) {
                        throw new EOFException("BinaryBufferedFile, no bytes at all, trying to read "
                                + minlength);
                    } else {
                        throw new FormatException("BinaryBufferedFile: failed to read "
                                + minlength
                                + " bytes, with "
                                + bytesinbuffer
                                + " bytes in the buffer and "
                                + available()
                                + " bytes available, have read "
                                + curptr
                                + " bytes.");
                    }
                }
                bytesinbuffer += err;
                assertSize(minlength);
            }
        } catch (EOFException e) {
            throw e;
        } catch (IOException i) {
            throw new FormatException("assertSize IOException: "
                    + i.getMessage());
        }
    }

    public long skipBytes(long n) throws IOException {
        if (n < bytesinbuffer) {
            bytesinbuffer -= n;
            curptr += n;
            return n;
        }
        final long oldbinb = bytesinbuffer;
        bytesinbuffer = 0;
        curptr = 0;
        final int skipcnt = (int) super.skipBytes(n - oldbinb);
        firstbyteoffset += skipcnt;
        return (oldbinb + skipcnt);
    }

    public long getFilePointer() throws IOException {
        return (firstbyteoffset + curptr);
    }

    public void seek(long pos) throws IOException {
        final long relpos = pos - firstbyteoffset;
        if ((relpos >= 0) && (relpos < (curptr + bytesinbuffer))) {
            final int relcur = (int) relpos - curptr;
            if (relcur != 0) {
                bytesinbuffer -= relcur;
                curptr = (int) relpos;
            } // else we're already at the right place
        } else {
            super.seek(pos);
            firstbyteoffset = pos;
            bytesinbuffer = 0;
            curptr = 0;
        }
    }

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

    public long available() throws IOException {
        return (length() - firstbyteoffset - curptr);
    }

    /**
     * Disposes the underlying file input, and releases some resources of the
     * class. Calling any other members after this one will return bogus
     * results.
     *
     * @exception IOException IO errors envountered in closing the file
     */
    public void dispose() throws IOException {
        buffer = null;
        super.dispose();
    }

    public int read() throws IOException {
        try {
            if (bytesinbuffer == 0)
                refillBuffer();
        } catch (EOFException e) {
            return -1;
        }
        bytesinbuffer--;
        return MoreMath.signedToInt(buffer[curptr++]);
    }

    /**
     * Read from the file
     *
     * @param b The byte array to read into
     * @param off the first array position to read into
     * @param len the number of bytes to read
     * @return the number of bytes read
     * @exception IOException Any IO errors encountered in reading from the file
     */
    public int read(byte b[], int off, int len) throws IOException {
        int numread = 0;
        int copy;
        if (len < bytesinbuffer)
            copy = len;
        else
            copy = bytesinbuffer;
        numread += copy;
        bytesinbuffer -= copy;
        System.arraycopy(buffer, curptr, b, off, copy);
        curptr += copy;
        off += copy;

        if (len == copy)
            return numread;

        len -= copy;
        // was not enough stuff in buffer, do some reads...

        if (len > 512) {// threshold exceeded, read straight into user
            // buffer

            final int bcnt = super.read(b, off, len);
            firstbyteoffset += (curptr + bcnt);
            curptr = 0;
            return (numread + bcnt);

        } else { // refill buffer and recurse

            try {
                refillBuffer();
            } catch (EOFException e) {
                if (numread == 0) {
                    // If it's really EOF and nothing was ever read (as opposed
                    // to getting a little out of the buffer before the EOF),
                    // return EOF value
                    numread = -1;
                }
                return numread;
            }
            return (numread + read(b, off, len));

        }
    }

    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }

    /**
     * Read from the file.
     *
     * @param howmany the number of bytes to read
     * @param allowless if we can return fewer bytes than requested
     * @return the array of bytes read.
     * @exception FormatException Any IO Exceptions, plus an end-of-file
     *            encountered after reading some, but now enough, bytes when
     *            allowless was <code>false</code>
     * @exception EOFException Encountered an end-of-file while allowless was
     *            <code>false</code>, but NO bytes had been read.
     */
    public byte[] readBytes(int howmany, boolean allowless)
            throws EOFException, FormatException {

        byte foo[] = new byte[howmany];
        int gotsofar = 0;
        try {
            while (gotsofar < howmany) {
                int err = read(foo, gotsofar, howmany - gotsofar);
                if (err == -1) {
                    if (allowless) {
                        /*
                         * return a smaller array, so the caller can tell how
                         * much they really got
                         */
                        byte retval[] = new byte[gotsofar];
                        System.arraycopy(foo, 0, retval, 0, gotsofar);
                        return retval;
                    } else { // some kind of failure...
                        if (gotsofar > 0) {
                            throw new FormatException("EOF while reading");
                        } else {
                            throw new EOFException();
                        }
                    }
                }

                gotsofar += err;
            }
        } catch (IOException i) {
            throw new FormatException("IOException reading file: "
                    + i.getMessage());
        }
        return foo;
    }

    /**
     * Reads and returns a single byte, cast to a char.
     *
     * @return the byte read from the file, cast to a char
     * @exception EOFException the end-of-file has been reached, so no chars
     *            where available
     * @exception FormatException a rethrown IOException
     */
    public char readChar() throws EOFException, FormatException {
        try {
            int retv = read();
            if (retv == -1) {
                throw new EOFException("Error in ReadChar, EOF reached");
            }
            return (char) retv;
        } catch (IOException i) {
            throw new FormatException("IOException in ReadChar: "
                    + i.getMessage());
        }
    }

    /**
     * Reads and returns a short.
     *
     * @return the 2 bytes merged into a short, according to the current byte
     *         ordering
     * @exception EOFException there were less than 2 bytes left in the file
     * @exception FormatException rethrow of IOExceptions encountered while
     *            reading the bytes for the short
     * @see #read(byte[])
     */
    public short readShort() throws EOFException, FormatException {
        // MSBFirst must be set when we are called
        assertSize(2);
        curptr += 2;
        bytesinbuffer -= 2;
        return MoreMath.BuildShort(buffer, curptr - 2, MSBFirst);
    }

    /**
     * Reads and returns a integer from 2 bytes.
     *
     * @return the 2 bytes merged into a short, according to the current byte
     *         ordering, and then unsigned to int.
     * @exception EOFException there were less than 2 bytes left in the file
     * @exception FormatException rethrow of IOExceptions encountered while
     *            reading the bytes for the short
     * @see #read(byte[])
     */
    public int readUnsignedShort() throws EOFException, FormatException {
        // MSBFirst must be set when we are called
        return MoreMath.signedToInt(readShort());
    }

    /**
     * Reads an array of shorts.
     *
     * @param vec the array to write the shorts into
     * @param offset the first array index to write to
     * @param len the number of shorts to read
     * @exception EOFException there were fewer bytes than needed in the file
     * @exception FormatException rethrow of IOExceptions encountered while
     *            reading the bytes for the array
     */
    public void readShortArray(short vec[], int offset, int len)
            throws EOFException, FormatException {

        while (len > 0) {
            int shortsleft = bytesinbuffer / 2;
            if (shortsleft == 0) {
                assertSize(2); // force a buffer refill - throws
                // exception if it can't
                continue;
            }
            int reallyread = (len < shortsleft) ? len : shortsleft;
            if (MSBFirst) {
                for (int i = 0; i < reallyread; i++) {
                    vec[offset++] = MoreMath.BuildShortBE(buffer, curptr);
                    curptr += 2;
                }
            } else {
                for (int i = 0; i < reallyread; i++) {
                    vec[offset++] = MoreMath.BuildShortLE(buffer, curptr);
                    curptr += 2;
                }
            }
            len -= reallyread;
            bytesinbuffer -= (2 * reallyread);
        }
    }

    /**
     * Reads and returns a long.
     *
     * @return the 4 bytes merged into a long, according to the current byte
     *         ordering
     * @exception EOFException there were less than 4 bytes left in the file
     * @exception FormatException rethrow of IOExceptions encountered while
     *            reading the bytes for the integer
     */
    public int readInteger() throws EOFException, FormatException {
        // MSBFirst must be set when we are called
        assertSize(4);
        curptr += 4;
        bytesinbuffer -= 4;
        return MoreMath.BuildInteger(buffer, curptr - 4, MSBFirst);
    }

    /**
     * Reads an array of integers.
     *
     * @exception EOFException there were fewer bytes than needed in the file
     * @exception FormatException rethrow of IOExceptions encountered while
     *            reading the bytes for the array
     */
    public void readIntegerArray(int vec[], int offset, int len)
            throws EOFException, FormatException {
        while (len > 0) {
            int intsleft = bytesinbuffer / 4;
            if (intsleft == 0) {
                assertSize(4); // force a buffer refill
                continue;
            }
            int reallyread = (len < intsleft) ? len : intsleft;
            int cursor = curptr;
            if (MSBFirst) {
                for (int i = 0; i < reallyread; i++) {
                    vec[offset++] = MoreMath.BuildIntegerBE(buffer, cursor);
                    cursor += 4;
                }
            } else {
                for (int i = 0; i < reallyread; i++) {
                    vec[offset++] = MoreMath.BuildIntegerLE(buffer, cursor);
                    cursor += 4;
                }
            }
            len -= reallyread;
            bytesinbuffer -= (4 * reallyread);
            curptr = cursor;
        }
    }

    /**
     * Reads an array of floats from the input.
     *
     * @param vec the vector to read into
     * @param offset the first float read goes into vec[offset]
     * @param len the number of floats to read from the stream
     * @exception EOFException not enough bytes were left in the file
     * @exception FormatException rethrow of IOExceptions encountered while
     *            reading the bytes for the integer
     */
    public void readFloatArray(float vec[], int offset, int len)
            throws EOFException, FormatException {
        while (len > 0) {
            int floatsleft = bytesinbuffer / 4;
            if (floatsleft == 0) {
                assertSize(4); // force a buffer refill
                continue;
            }
            int reallyread = (len < floatsleft) ? len : floatsleft;
            int cursor = curptr;
            if (MSBFirst) {
                for (int i = 0; i < reallyread; i++) {
                    int floatasint = MoreMath.BuildIntegerBE(buffer, cursor);
                    vec[offset++] = Float.intBitsToFloat(floatasint);
                    cursor += 4;
                }
            } else {
                for (int i = 0; i < reallyread; i++) {
                    int floatasint = MoreMath.BuildIntegerLE(buffer, cursor);
                    vec[offset++] = Float.intBitsToFloat(floatasint);
                    cursor += 4;
                }
            }
            len -= reallyread;
            bytesinbuffer -= (4 * reallyread);
            curptr = cursor;
        }
    }

    /**
     * Reads and returns a long.
     *
     * @return the 8 bytes merged into a long, according to the current byte
     *         ordering
     * @exception EOFException there were less than 8 bytes left in the file
     * @exception FormatException rethrow of IOExceptions encountered while
     *            reading the bytes for the long
     * @see #read(byte[])
     */
    public long readLong() throws EOFException, FormatException {
        assertSize(8);
        curptr += 8;
        bytesinbuffer -= 8;
        return MoreMath.BuildLong(buffer, curptr - 8, MSBFirst);
    }

    /**
     * Reads <code>length</code> bytes and returns a string composed of the
     * bytes cast to chars.
     *
     * @param length the number of bytes to read into the string
     * @return the composed string
     * @exception EOFException there were less than <code>length</code> bytes
     *            left in the file
     * @exception FormatException rethrow of IOExceptions encountered while
     *            reading the bytes for the short
     */
    public String readFixedLengthString(int length) throws EOFException,
            FormatException {
        String retstring;
        if (length < buffer.length) {
            assertSize(length);
            retstring = new String(buffer, curptr, length);
            curptr += length;
            bytesinbuffer -= length;
        } else {
            byte foo[] = readBytes(length, false);
            retstring = new String(foo, 0, length);
        }
        return retstring;
    }
}
TOP

Related Classes of com.bbn.openmap.io.BinaryBufferedFile

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.