Package com.bbn.openmap.io

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

// **********************************************************************
//
// <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/StreamInputReader.java,v $
// $RCSfile: StreamInputReader.java,v $
// $Revision: 1.2.2.2 $
// $Date: 2007/06/21 21:41:28 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap.io;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;

import com.bbn.openmap.util.Debug;

/**
* An Abstract InputReader to handle reading data from streams, where
* seeking to a place in the file in front of the current pointer
* involves closing the stream, and re-seeking from the beginning.
*
* @see com.bbn.openmap.io.InputReader
* @see com.bbn.openmap.io.BinaryFile
*/
public abstract class StreamInputReader implements InputReader {

    /**
     * The underlying data input stream, for resource files. Is used
     * if the inputFile is null.
     */
    protected InputStream inputStream = null;

    /**
     * Keep track of how many bytes have been read when using the
     * DataInputStream to read the file.
     */
    protected long inputStreamCount = 0;

    /**
     * The source name.
     */
    protected String name = null;

    public String getName() {
        return name;
    }

    /**
     * Add the number of bytes to the inputStreamCount.
     *
     * @return number of bytes added in this call, to pass along to
     *         anything else that will be interested.
     */
    protected int count(int add) {
        inputStreamCount += add;
        return (int) add;
    }

    /**
     * Reset the DataInputStream to the beginning, by closing the
     * current connection and reopening it. The StreamInputReader
     * method simply closes the input stream and resets the input
     * stream count, so the implementation of this class needs to
     * reopen the stream at the beginning of the source file.
     */
    protected void reopen() throws IOException {
        if (inputStream != null) {
            Debug.message("binaryfile",
                    "StreamInputReader: Closing inputStream");
            inputStream.close();
        }

        inputStreamCount = 0;
    }

    /**
     * Skip over n bytes in the input file
     *
     * @param n the number of bytes to skip
     * @return the actual number of bytes skipped. annoying, isn't it?
     * @exception IOException Any IO errors that occur in skipping
     *            bytes in the underlying file
     */
    public long skipBytes(long n) throws IOException {

        long count = 0;
        long gotsofar = 0;

        while (count < n) {
            gotsofar = inputStream.skip(n - count);
            if (gotsofar == 0) { // added from david marklund
                Debug.error("StreamInputReader can't skip " + n
                        + " bytes as instructed");
                break;
            }
            count += gotsofar;
        }

        count((int) count);
        return count;
    }

    /**
     * Get the index of the next character to be read
     *
     * @return the index
     * @exception IOException Any IO errors that occur in accessing
     *            the underlying file
     */
    public long getFilePointer() throws IOException {
        return inputStreamCount;
    }

    /**
     * Set the index of the next character to be read.
     *
     * @param pos the position to seek to.
     * @exception IOException Any IO Errors that occur in seeking the
     *            underlying file.
     */
    public void seek(long pos) throws IOException {
        boolean seekComments = false;
        long skipped;
        if (Debug.debugging("binaryfileseek")) {
            seekComments = true;
        }

        long curPosition = inputStreamCount;
        if (pos >= curPosition) {
            if (seekComments) {
                Debug.output("StreamInputReader - seeking to " + pos + " from "
                        + curPosition);
            }

            skipped = skipBytes(pos - curPosition);

            if (seekComments) {
                Debug.output("   now at: " + inputStreamCount
                        + ", having skipped " + skipped);
            }
        } else {
            if (seekComments) {
                Debug.output("StreamInputReader - having to start over for seek - "
                        + pos + " from " + curPosition);
            }
            reopen();
            if (seekComments)
                Debug.output("   skipping to: " + pos);
            skipped = skipBytes(pos);
            if (seekComments) {
                Debug.output("   now at: " + inputStreamCount
                        + ", having skipped " + skipped);
            }
        }
    }

    /**
     * Return how many bytes the input stream thinks make up the file.
     * This is calculated by adding the number of bytes read to the
     * number of bytes available. May not be reliable.
     *
     * @return the number of bytes remaining to be read (counted in
     *         bytes)
     * @exception IOException Any IO errors encountered in accessing
     *            the file
     */
    public long length() throws IOException {
        return inputStreamCount + inputStream.available();
    }

    /**
     * Return how many bytes the input stream thinks are available.
     *
     * @return the number of bytes remaining to be read (counted in
     *         bytes)
     * @exception IOException Any IO errors encountered in accessing
     *            the file
     */
    public long available() throws IOException {
        return inputStream.available();
    }

    /**
     * Closes the underlying file
     *
     * @exception IOException Any IO errors encountered in accessing
     *            the file
     */
    public void close() throws IOException {
        try {
            Debug.message("binaryfile", "StreamInputReader.close()");

            // From the Sun Network Programming Guide for 1.4, if
            // there are
            // problems with Connection reset by peer, then you should
            // do this before closing the stream, giving all the data
            // a chance to be read. Haven't decided to do this by
            // default, but put it in here for easy access if people
            // decided they need it.
            if (Debug.debugging("connection_problems")) {
                Thread.sleep(1000);
            }

            if (inputStream != null)
                inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        inputStream = null;
    }

    /**
     * Read from the file.
     *
     * @return one byte from the file. -1 for EOF
     * @exception IOException Any IO errors encountered in reading
     *            from the file
     */
    public int read() throws IOException {
        count(1);
        return inputStream.read();
    }

    /**
     * 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 gotsofar = 0;
        while (gotsofar < len) {
            int read = inputStream.read(b, off + gotsofar, len - gotsofar);
            if (read == -1) {
                if (gotsofar > 0) {
                    // Hit the EOF in the middle of the loop.
                    return gotsofar;
                } else {
                    return read;
                }
            } else {
                gotsofar += read;
            }
        }

        count(gotsofar);
        return gotsofar;
    }

    /**
     * Read from the file.
     *
     * @param b the byte array to read into. Equivelent to
     *        <code>read(b, 0, b.length)</code>
     * @return the number of bytes read
     * @exception IOException Any IO errors encountered in reading
     *            from the file
     * @see java.io.RandomAccessFile#read(byte[])
     */
    public int read(byte b[]) throws IOException {
        return inputStream.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;
        int err = 0;
        try {
            while (gotsofar < howmany) {
                err = inputStream.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);
                        count(gotsofar);
                        return retval;
                    } else { //some kind of failure...
                        if (gotsofar > 0) {
                            throw new FormatException("StreamInputReader: EOF while reading data");
                        } else {
                            throw new EOFException();
                        }
                    }
                }
                gotsofar += err;
            }
        } catch (IOException i) {
            throw new FormatException("StreamInputReader: readBytes IOException: "
                    + i.getMessage());
        }
        count(howmany);
        return foo;
    }

}
TOP

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

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.