private NPOIFSFileSystem(FileChannel channel, boolean closeChannelOnError) throws IOException {
    this(false);

    try {
      // Get the header
      ByteBuffer headerBuffer = ByteBuffer.allocate(POIFSConstants.SMALLER_BIG_BLOCK_SIZE);
      IOUtils.readFully(channel, headerBuffer);

      // Have the header processed
      _header = new HeaderBlock(headerBuffer);

      // Now process the various entries
      _data = new FileBackedDataSource(channel);
      readCoreContents();
    } catch (IOException e) {
      if (closeChannelOnError) {
        channel.close();
      }
      throw e;
    } catch (RuntimeException e) {
      // Comes from Iterators etc.
      // TODO Decide if we can handle these better whilst
      //  still sticking to the iterator contract
      if (closeChannelOnError) {
        channel.close();
      }
      throw e;
    }
  }
  /**
   * Create a POIFSFileSystem from an <tt>InputStream</tt>. Normally the stream is read until EOF.
   * The stream is always closed.
   *
   * <p>Some streams are usable after reaching EOF (typically those that return <code>true</code>
   * for <tt>markSupported()</tt>). In the unlikely case that the caller has such a stream
   * <i>and</i> needs to use it after this constructor completes, a work around is to wrap the
   * stream in order to trap the <tt>close()</tt> call. A convenience method (
   * <tt>createNonClosingInputStream()</tt>) has been provided for this purpose:
   *
   * <pre>
   * InputStream wrappedStream = POIFSFileSystem.createNonClosingInputStream(is);
   * HSSFWorkbook wb = new HSSFWorkbook(wrappedStream);
   * is.reset();
   * doSomethingElse(is);
   * </pre>
   *
   * Note also the special case of <tt>ByteArrayInputStream</tt> for which the <tt>close()</tt>
   * method does nothing.
   *
   * <pre>
   * ByteArrayInputStream bais = ...
   * HSSFWorkbook wb = new HSSFWorkbook(bais); // calls bais.close() !
   * bais.reset(); // no problem
   * doSomethingElse(bais);
   * </pre>
   *
   * @param stream the InputStream from which to read the data
   * @exception IOException on errors reading, or on invalid data
   */
  public NPOIFSFileSystem(InputStream stream) throws IOException {
    this(false);

    ReadableByteChannel channel = null;
    boolean success = false;

    try {
      // Turn our InputStream into something NIO based
      channel = Channels.newChannel(stream);

      // Get the header
      ByteBuffer headerBuffer = ByteBuffer.allocate(POIFSConstants.SMALLER_BIG_BLOCK_SIZE);
      IOUtils.readFully(channel, headerBuffer);

      // Have the header processed
      _header = new HeaderBlock(headerBuffer);

      // Sanity check the block count
      BlockAllocationTableReader.sanityCheckBlockCount(_header.getBATCount());

      // We need to buffer the whole file into memory when
      //  working with an InputStream.
      // The max possible size is when each BAT block entry is used
      int maxSize = BATBlock.calculateMaximumSize(_header);
      ByteBuffer data = ByteBuffer.allocate(maxSize);
      // Copy in the header
      headerBuffer.position(0);
      data.put(headerBuffer);
      data.position(headerBuffer.capacity());
      // Now read the rest of the stream
      IOUtils.readFully(channel, data);
      success = true;

      // Turn it into a DataSource
      _data = new ByteArrayBackedDataSource(data.array(), data.position());
    } finally {
      // As per the constructor contract, always close the stream
      if (channel != null) channel.close();
      closeInputStream(stream, success);
    }

    // Now process the various entries
    readCoreContents();
  }