/* * ImageI/O-Ext - OpenSource Java Image translation Library * http://www.geo-solutions.it/ * https://imageio-ext.dev.java.net/ * (C) 2007 - 2008, GeoSolutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.esa.s1tbx.io; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageInputStreamImpl; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteOrder; /** * An implementation of {@link ImageInputStream} that gets its input from a * {@link File}. The eraf contents are assumed to be stable during the lifetime * of the object. * * @author Simone Giannecchini, GeoSolutions */ public final class FileImageInputStreamExtImpl extends ImageInputStreamImpl implements ImageInputStream { /** * the associated {@link File} */ protected File file; protected EnhancedRandomAccessFile eraf; private boolean isClosed = false; public static ImageInputStream createInputStream(final File file) throws IOException { return new FileImageInputStreamExtImpl(file); //return new FileImageInputStream(file); } @Override public byte readByte() throws IOException { return eraf.readByte(); } @Override public char readChar() throws IOException { return eraf.readChar(); } @Override public double readDouble() throws IOException { return eraf.readDouble(); } @Override public float readFloat() throws IOException { return eraf.readFloat(); } @Override public void readFully(byte[] b, int off, int len) throws IOException { eraf.readFully(b, off, len); } @Override public void readFully(byte[] b) throws IOException { eraf.readFully(b); } @Override public int readInt() throws IOException { return eraf.readInt(); } @Override public String readLine() throws IOException { return eraf.readLine(); } @Override public ByteOrder getByteOrder() { return eraf.getByteOrder(); } @Override public long getStreamPosition() throws IOException { return eraf.getFilePointer(); } @Override public boolean isCached() { return eraf.isCached(); } @Override public int read(byte[] b) throws IOException { return eraf.read(b); } @Override public long skipBytes(long n) throws IOException { return eraf.skipBytes(n); } @Override public long readLong() throws IOException { return eraf.readLong(); } @Override public short readShort() throws IOException { return eraf.readShort(); } @Override public int readUnsignedByte() throws IOException { return eraf.readUnsignedByte(); } @Override public long readUnsignedInt() throws IOException { return eraf.readUnsignedInt(); } @Override public int readUnsignedShort() throws IOException { return eraf.readUnsignedShort(); } @Override public String readUTF() throws IOException { return eraf.readUTF(); } @Override public void setByteOrder(ByteOrder byteOrder) { eraf.setByteOrder(byteOrder); super.setByteOrder(byteOrder); } @Override public int skipBytes(int n) throws IOException { return eraf.skipBytes(n); } /** * Constructs a {@link FileImageInputStreamExtImpl} that will read from a * given {@link File}. * <p/> * <p/> * The eraf contents must not change between the time this object is * constructed and the time of the last call to a read method. * * @param f a {@link File} to read from. * @throws NullPointerException if <code>f</code> is <code>null</code>. * @throws SecurityException if a security manager exists and does not allow read * access to the eraf. * @throws FileNotFoundException if <code>f</code> is a directory or cannot be opened * for reading for any other reason. * @throws IOException if an I/O error occurs. */ public FileImageInputStreamExtImpl(File f) throws FileNotFoundException, IOException { this(f, -1); } /** * Constructs a {@link FileImageInputStreamExtImpl} that will read from a * given {@link File}. * <p/> * <p/> * The eraf contents must not change between the time this object is * constructed and the time of the last call to a read method. * * @param f a {@link File} to read from. * @param bufferSize size of the underlying buffer. * @throws NullPointerException if <code>f</code> is <code>null</code>. * @throws SecurityException if a security manager exists and does not allow read * access to the eraf. * @throws FileNotFoundException if <code>f</code> is a directory or cannot be opened * for reading for any other reason. * @throws IOException if an I/O error occurs. */ public FileImageInputStreamExtImpl(File f, int bufferSize) throws IOException { // // // // Check that the input file is a valid file // // // if (f == null) { throw new NullPointerException("f == null!"); } final StringBuilder buff = new StringBuilder( "Invalid input file provided"); if (!f.exists() || f.isDirectory()) { buff.append("exists: ").append(f.exists()).append("\n"); buff.append("isDirectory: ").append(f.isDirectory()).append("\n"); throw new FileNotFoundException(buff.toString()); } if (!f.exists() || f.isDirectory() || !f.canRead()) { buff.append("canRead: ").append(f.canRead()).append("\n"); throw new IOException(buff.toString()); } this.file = f; this.eraf = bufferSize <= 0 ? new EnhancedRandomAccessFile(f, "r") : new EnhancedRandomAccessFile(f, "r", bufferSize); // NOTE: this must be done accordingly to what ImageInputStreamImpl // does, otherwise some ImageReader subclasses might not work. this.eraf.setByteOrder(ByteOrder.BIG_ENDIAN); } /** * Reads an int from the underlying {@link EnhancedRandomAccessFile}. */ @Override public int read() throws IOException { //checkClosed(); bitOffset = 0; int val = eraf.read(); if (val != -1) { ++streamPos; } return val; } /** * Read up to <code>len</code> bytes into an array, at a specified offset. * This will block until at least one byte has been read. * * @param b the byte array to receive the bytes. * @param off the offset in the array where copying will start. * @param len the number of bytes to copy. * @return the actual number of bytes read, or -1 if there is not more data * due to the end of the eraf being reached. */ @Override public int read(byte[] b, int off, int len) throws IOException { //checkClosed(); bitOffset = 0; int nbytes = eraf.readBytes(b, off, len); if (nbytes != -1) { streamPos += nbytes; } return nbytes; } /** * Returns the length of the underlying eraf, or <code>-1</code> if it is * unknown. * * @return the eraf length as a <code>long</code>, or <code>-1</code>. */ @Override public long length() { try { //checkClosed(); return eraf.length(); } catch (IOException e) { return -1L; } } /** * Seeks the current position to pos. */ @Override public void seek(long pos) throws IOException { //checkClosed(); //if (pos < flushedPos) { // throw new IllegalArgumentException("pos < flushedPos!"); //} bitOffset = 0; streamPos = eraf.seek(pos); } /** * Closes the underlying {@link EnhancedRandomAccessFile}. * * @throws IOException in case something bad happens. */ @Override public void close() throws IOException { try { if (!isClosed) { super.close(); eraf.close(); } } finally { isClosed = true; } } /** * Retrieves the {@link File} we are connected to. */ public File getFile() { return file; } /** * Disposes this {@link FileImageInputStreamExtImpl} by closing its * underlying {@link EnhancedRandomAccessFile}. */ public void dispose() { try { close(); } catch (IOException e) { // } } /** * Provides a simple description for this {@link ImageInputStream}. * * @return a simple description for this {@link ImageInputStream}. */ @Override public String toString() { return "FileImageInputStreamExtImpl which points to " + this.file.toString(); } }