LazyFileInputStream.java

  1. package de.japrost.jabudget.serialization;

  2. import java.io.File;
  3. import java.io.FileDescriptor;
  4. import java.io.FileInputStream;
  5. import java.io.FileNotFoundException;
  6. import java.io.IOException;
  7. import java.io.InputStream;
  8. import java.io.OutputStream;
  9. import java.nio.channels.FileChannel;

  10. /**
  11.  * An {@link InputStream} that uses a {@link FileInputStream} internally, which is created when the first acces is done.
  12.  * On {@link InputStream#close()} the internal {@link FileInputStream} will be closed and unset that next reading all
  13.  * will get a new stream.
  14.  */
  15. // TODO move to a io project
  16. public class LazyFileInputStream extends InputStream {

  17.     private final File file;
  18.     private FileInputStream delegate;

  19.     /**
  20.      * Create a {@link LazyFileInputStream} to be based on the given {@link File}.
  21.      *
  22.      * @param file the file to use in the delegate.
  23.      */
  24.     public LazyFileInputStream(final File file) {
  25.         // TODO require non null
  26.         this.file = file;
  27.     }

  28.     /**
  29.      * {@inheritDoc}
  30.      * <p>
  31.      * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
  32.      * {@link FileInputStream#read()}.
  33.      */
  34.     @Override
  35.     public int read() throws IOException {
  36.         if (delegate == null) {
  37.             initDelegate();
  38.         }
  39.         return delegate.read();
  40.     }

  41.     /**
  42.      * {@inheritDoc}
  43.      * <p>
  44.      * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
  45.      * {@link FileInputStream#read(byte[])}.
  46.      */
  47.     @Override
  48.     public int read(final byte[] b) throws IOException {
  49.         if (delegate == null) {
  50.             initDelegate();
  51.         }
  52.         return delegate.read(b);
  53.     }

  54.     /**
  55.      * {@inheritDoc}
  56.      * <p>
  57.      * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
  58.      * {@link FileInputStream#read(byte[], int, int)}.
  59.      */
  60.     @Override
  61.     public int read(final byte[] b, final int off, final int len) throws IOException {
  62.         if (delegate == null) {
  63.             initDelegate();
  64.         }
  65.         return delegate.read(b, off, len);
  66.     }

  67.     /**
  68.      * {@inheritDoc}
  69.      * <p>
  70.      * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
  71.      * {@link FileInputStream#readNBytes(byte[], int, int)}.
  72.      */
  73.     @Override
  74.     public int readNBytes(final byte[] b, final int off, final int len) throws IOException {
  75.         if (delegate == null) {
  76.             initDelegate();
  77.         }
  78.         return delegate.readNBytes(b, off, len);
  79.     }

  80.     /**
  81.      * {@inheritDoc}
  82.      * <p>
  83.      * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
  84.      * {@link FileInputStream#readAllBytes()}.
  85.      */
  86.     @Override
  87.     public byte[] readAllBytes() throws IOException {
  88.         if (delegate == null) {
  89.             initDelegate();
  90.         }
  91.         return delegate.readAllBytes();
  92.     }

  93.     /**
  94.      * {@inheritDoc}
  95.      * <p>
  96.      * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
  97.      * {@link FileInputStream#skip(long)}.
  98.      */
  99.     @Override
  100.     public long skip(final long n) throws IOException {
  101.         if (delegate == null) {
  102.             initDelegate();
  103.         }
  104.         return delegate.skip(n);
  105.     }

  106.     /**
  107.      * {@inheritDoc}
  108.      * <p>
  109.      * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
  110.      * {@link FileInputStream#available()}.
  111.      */
  112.     @Override
  113.     public int available() throws IOException {
  114.         if (delegate == null) {
  115.             initDelegate();
  116.         }
  117.         return delegate.available();
  118.     }

  119.     /**
  120.      * {@inheritDoc}
  121.      * <p>
  122.      * <strong>This implementation</strong> calls {@link FileInputStream#close()} on the delegate and unassignes the
  123.      * delegate.
  124.      */
  125.     @Override
  126.     public void close() throws IOException {
  127.         if (delegate != null) {
  128.             delegate.close();
  129.             delegate = null;
  130.         }
  131.     }

  132.     /**
  133.      * Initializes the delegate if not already done and delegates to {@link FileInputStream#getChannel()}.
  134.      *
  135.      * @return {@link FileInputStream#getChannel()}
  136.      * @throws FileNotFoundException see {@link FileInputStream#FileInputStream(File)}.
  137.      */
  138.     public FileChannel getChannel() throws FileNotFoundException {
  139.         if (delegate == null) {
  140.             initDelegate();
  141.         }
  142.         return delegate.getChannel();
  143.     }

  144.     /**
  145.      * Initializes the delegate if not already done and delegates to {@link FileInputStream#getFD()}.
  146.      *
  147.      * @return {@link FileInputStream#getFD()}
  148.      * @throws IOException see {@link FileInputStream#getFD()}
  149.      */
  150.     public final FileDescriptor getFD() throws IOException {
  151.         if (delegate == null) {
  152.             initDelegate();
  153.         }
  154.         return delegate.getFD();
  155.     }

  156.     /**
  157.      * {@inheritDoc}
  158.      * <p>
  159.      * <strong>This implementation</strong> initializes the delegate if not already done and delegates to
  160.      * {@link FileInputStream#transferTo(OutputStream)}.
  161.      */
  162.     @Override
  163.     public long transferTo(final OutputStream out) throws IOException {
  164.         if (delegate == null) {
  165.             initDelegate();
  166.         }
  167.         return delegate.transferTo(out);
  168.     }

  169.     /**
  170.      * Tell if the delegate is initialized.
  171.      *
  172.      * @return {@code true} if there is a delegate.
  173.      */
  174.     public boolean isOpen() {
  175.         return delegate != null;
  176.     }

  177.     private void initDelegate() throws FileNotFoundException {
  178.         delegate = new FileInputStream(file);
  179.     }

  180. }