/* * ImageI/O-Ext - OpenSource Java Image translation Library * http://www.geo-solutions.it/ * http://java.net/projects/imageio-ext/ * (C) 2007 - 2009, 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; * either version 3 of the License, or (at your option) any later version. * * 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 it.geosolutions.imageio.stream.output; import it.geosolutions.imageio.stream.eraf.EnhancedRandomAccessFile; import it.geosolutions.imageio.stream.input.FileImageInputStreamExtImpl; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteOrder; import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.ImageOutputStreamImpl; /** * An implementation of {@link ImageOutputStream} that take its output on a * {@link File}. * * @author Daniele Romagnoli, GeoSolutions * @author Simone Giannecchini, GeoSolutions */ public class FileImageOutputStreamExtImpl extends ImageOutputStreamImpl implements FileImageOutputStreamExt { private EnhancedRandomAccessFile eraf; private File file; private boolean isClosed; /** * A constructor which accepts a File as input. * * @param eraf * * @throws FileNotFoundException * @throws IOException */ public FileImageOutputStreamExtImpl(File file) throws FileNotFoundException, IOException { this.file = file; eraf = new EnhancedRandomAccessFile(file, "rw"); // NOTE: this must be done accordingly to what ImageInputStreamImpl // does, otherwise some ImageREader subclasses might not work. this.eraf.setByteOrder(ByteOrder.BIG_ENDIAN); } /** * A constructor which accepts a File as input. * * @param eraf * @param bufSize * * @throws FileNotFoundException * @throws IOException */ public FileImageOutputStreamExtImpl(File file, int bufSize) throws FileNotFoundException, IOException { this.file = file; eraf = new EnhancedRandomAccessFile(file, "rw", bufSize); // NOTE: this must be done accordingly to what ImageInputStreamImpl // does, otherwise some ImageREader subclasses might not work. this.eraf.setByteOrder(ByteOrder.BIG_ENDIAN); } public int read() throws IOException { checkClosed(); bitOffset = 0; int val = eraf.read(); if (val != -1) { ++streamPos; } return val; } public int read(byte[] b, int off, int len) throws IOException { checkClosed(); bitOffset = 0; int nbytes = eraf.read(b, off, len); if (nbytes != -1) { streamPos += nbytes; } return nbytes; } public void write(int b) throws IOException { checkClosed(); flushBits(); eraf.write(b); ++streamPos; } public void write(byte[] b, int off, int len) throws IOException { checkClosed(); flushBits(); eraf.write(b, off, len); streamPos += len; } public long length() { try { checkClosed(); return eraf.length(); } catch (IOException e) { return -1L; } } /** * Sets the current stream position and resets the bit offset to 0. It is * legal to seeking past the end of the eraf; an <code>EOFException</code> * will be thrown only if a read is performed. The eraf length will not be * increased until a write is performed. * * @exception IndexOutOfBoundsException * if <code>pos</code> is smaller than the flushed * position. * @exception IOException * if any other I/O error occurs. */ public void seek(long pos) throws IOException { checkClosed(); if (pos < flushedPos) { throw new IndexOutOfBoundsException("pos < flushedPos!"); } bitOffset = 0; eraf.seek(pos); streamPos = eraf.getFilePointer(); } /** * Closes the underlying {@link EnhancedRandomAccessFile}. * * @throws IOException * in case something bad happens. */ 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 ImageOutputStream}. * * @return a simple description for this {@link ImageOutputStream}. */ public String toString() { return "FileImageOutputStreamExtImpl which points to " + this.file.toString(); } /** * Allows us to access the underlying file. * * @return the underlying {@link File}. */ public File getTarget() { return file; } public Class<File> getBinding() { return File.class; } }