// ********************************************************************** // // <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/FileInputReader.java,v $ // $RCSfile: FileInputReader.java,v $ // $Revision: 1.5 $ // $Date: 2008/10/24 21:28:21 $ // $Author: dietrick $ // // ********************************************************************** package com.bbn.openmap.io; import java.io.EOFException; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import com.bbn.openmap.util.Debug; /** * This class wraps a java.io.RandomAccessFile to allow us to choose the * byte-order of the underlying file. It has a user-settable byte-ordering, * which is then used to properly implement the various multibyte reading * members. Used for reading local files. * * @see java.io.RandomAccessFile * @see com.bbn.openmap.io.InputReader * @see com.bbn.openmap.io.BinaryFile */ public class FileInputReader implements InputReader { /** The underlying file input */ protected RandomAccessFile inputFile = null; /** * Needed for input reader interface. */ protected String name = null; /** * Needed for reopening files that have been closed. */ protected String absolutePath = null; /** * Constructs a new BinaryFile with the specified file as the input. The * default byte-order is LSB first. Reads start at the first byte of the * file. * * @param f the file to be opened for reading * @exception IOException pass-through errors from opening a * RandomAccessFile with f * @see java.io.RandomAccessFile */ public FileInputReader(File f) throws IOException { if (Debug.debugging("binaryfile")) { Debug.output("FileInputReader created from " + f.getAbsolutePath()); } name = f.getName(); absolutePath = f.getAbsolutePath(); inputFile = init(f); } /** * Constructs a new BinaryFile with the specified file as the input. The * default byte-order is LSB first. Reads start at the first byte of the * file. * * @param f the path to the file to be opened for reading. * @exception IOException pass-through errors from opening a * RandomAccessFile with f * @see java.io.RandomAccessFile */ public FileInputReader(String f) throws IOException { if (Debug.debugging("binaryfile")) { Debug.output("FileInputReader created from " + f); } File file = new File(f); name = file.getName(); absolutePath = file.getAbsolutePath(); inputFile = init(file); } /** * Get the file name. */ public String getName() { return name; } /** * @return the absolute path of the file. */ public String getAbsolutePath() { return absolutePath; } /** * Initialize the underlying RandomAccessFile. If it's found, but there are * too many files open, it calls BinaryFile.closeClosable to try to get an * open file pointer from the system, and then tries again. * * @param f a java.io.File * @throws IOException */ protected RandomAccessFile init(File f) throws IOException { RandomAccessFile inputFile = null; try { inputFile = new RandomAccessFile(f, "r"); } catch (IOException i) { if (i instanceof FileNotFoundException) { throw i; } if (f.canRead()) { BinaryFile.closeClosable(); inputFile = new RandomAccessFile(f, "r"); } else { throw i; } } return inputFile; } /** * Get the RandomAccessFile, for querying purposes only. Don't use it to get * data! */ public RandomAccessFile getInputFile() { return inputFile; } public RandomAccessFile checkInputFile() throws IOException { if (inputFile == null && absolutePath != null) { inputFile = init(new File(absolutePath)); } return inputFile; } /** * 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 { return checkInputFile().skipBytes((int) n); } /** * 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 checkInputFile().getFilePointer(); } /** * 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 { checkInputFile().seek(pos); } /** * Local files only. Retrieve the length of the file being accessed. * * @return the length of the file (counted in bytes) * @exception IOException Any IO errors that occur in accessing the * underlying file. */ public long length() throws IOException { return checkInputFile().length(); } /** * Return how many bytes left to be read in the file. * * @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 (length() - getFilePointer()); } /** * Closes the underlying file * * @exception IOException Any IO errors encountered in accessing the file */ public void close() throws IOException { if (Debug.debugging("binaryfile")) { Debug.output("FileInputReader.close()"); } try { if (inputFile != null) inputFile.close(); } catch (Exception e) { e.printStackTrace(); } inputFile = 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 { return checkInputFile().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 { return checkInputFile().read(b, off, len); } /** * Read from the file. * * @param b the byte array to read into. Equivalent 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 checkInputFile().read(b); } /** * 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 { RandomAccessFile inputFile = checkInputFile(); while (gotsofar < howmany) { err = inputFile.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 data"); } else { throw new EOFException(); } } } gotsofar += err; } } catch (IOException i) { throw new FormatException("FileInputReader: readBytes IOException: " + i.getMessage()); } return foo; } }