LazyFileInputStream.java
package de.japrost.jabudget.serialization;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
/**
* An {@link InputStream} that uses a {@link FileInputStream} internally, which is created when the first acces is done.
* On {@link InputStream#close()} the internal {@link FileInputStream} will be closed and unset that next reading all
* will get a new stream.
*/
// TODO move to a io project
public class LazyFileInputStream extends InputStream {
private final File file;
private FileInputStream delegate;
/**
* Create a {@link LazyFileInputStream} to be based on the given {@link File}.
*
* @param file the file to use in the delegate.
*/
public LazyFileInputStream(final File file) {
// TODO require non null
this.file = file;
}
/**
* {@inheritDoc}
* <p>
* <strong>This implementation</strong> initializes the delegate if not already done and delegates to
* {@link FileInputStream#read()}.
*/
@Override
public int read() throws IOException {
if (delegate == null) {
initDelegate();
}
return delegate.read();
}
/**
* {@inheritDoc}
* <p>
* <strong>This implementation</strong> initializes the delegate if not already done and delegates to
* {@link FileInputStream#read(byte[])}.
*/
@Override
public int read(final byte[] b) throws IOException {
if (delegate == null) {
initDelegate();
}
return delegate.read(b);
}
/**
* {@inheritDoc}
* <p>
* <strong>This implementation</strong> initializes the delegate if not already done and delegates to
* {@link FileInputStream#read(byte[], int, int)}.
*/
@Override
public int read(final byte[] b, final int off, final int len) throws IOException {
if (delegate == null) {
initDelegate();
}
return delegate.read(b, off, len);
}
/**
* {@inheritDoc}
* <p>
* <strong>This implementation</strong> initializes the delegate if not already done and delegates to
* {@link FileInputStream#readNBytes(byte[], int, int)}.
*/
@Override
public int readNBytes(final byte[] b, final int off, final int len) throws IOException {
if (delegate == null) {
initDelegate();
}
return delegate.readNBytes(b, off, len);
}
/**
* {@inheritDoc}
* <p>
* <strong>This implementation</strong> initializes the delegate if not already done and delegates to
* {@link FileInputStream#readAllBytes()}.
*/
@Override
public byte[] readAllBytes() throws IOException {
if (delegate == null) {
initDelegate();
}
return delegate.readAllBytes();
}
/**
* {@inheritDoc}
* <p>
* <strong>This implementation</strong> initializes the delegate if not already done and delegates to
* {@link FileInputStream#skip(long)}.
*/
@Override
public long skip(final long n) throws IOException {
if (delegate == null) {
initDelegate();
}
return delegate.skip(n);
}
/**
* {@inheritDoc}
* <p>
* <strong>This implementation</strong> initializes the delegate if not already done and delegates to
* {@link FileInputStream#available()}.
*/
@Override
public int available() throws IOException {
if (delegate == null) {
initDelegate();
}
return delegate.available();
}
/**
* {@inheritDoc}
* <p>
* <strong>This implementation</strong> calls {@link FileInputStream#close()} on the delegate and unassignes the
* delegate.
*/
@Override
public void close() throws IOException {
if (delegate != null) {
delegate.close();
delegate = null;
}
}
/**
* Initializes the delegate if not already done and delegates to {@link FileInputStream#getChannel()}.
*
* @return {@link FileInputStream#getChannel()}
* @throws FileNotFoundException see {@link FileInputStream#FileInputStream(File)}.
*/
public FileChannel getChannel() throws FileNotFoundException {
if (delegate == null) {
initDelegate();
}
return delegate.getChannel();
}
/**
* Initializes the delegate if not already done and delegates to {@link FileInputStream#getFD()}.
*
* @return {@link FileInputStream#getFD()}
* @throws IOException see {@link FileInputStream#getFD()}
*/
public final FileDescriptor getFD() throws IOException {
if (delegate == null) {
initDelegate();
}
return delegate.getFD();
}
/**
* {@inheritDoc}
* <p>
* <strong>This implementation</strong> initializes the delegate if not already done and delegates to
* {@link FileInputStream#transferTo(OutputStream)}.
*/
@Override
public long transferTo(final OutputStream out) throws IOException {
if (delegate == null) {
initDelegate();
}
return delegate.transferTo(out);
}
/**
* Tell if the delegate is initialized.
*
* @return {@code true} if there is a delegate.
*/
public boolean isOpen() {
return delegate != null;
}
private void initDelegate() throws FileNotFoundException {
delegate = new FileInputStream(file);
}
}