Tweak NPOIFS constructors so that if you have a FileChannel, you can pass it in, but that the File based one will tidy up after itself in the event of errors

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1054033 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2010-12-31 00:46:00 +00:00
parent f02e062521
commit 0057449df4
1 changed files with 64 additions and 15 deletions

View File

@ -107,7 +107,7 @@ public class NPOIFSFileSystem extends BlockStore
/** /**
* Creates a POIFSFileSystem from a <tt>File</tt>. This uses less memory than * Creates a POIFSFileSystem from a <tt>File</tt>. This uses less memory than
* creating from an <tt>InputStream</tt>. * creating from an <tt>InputStream</tt>. The File will be opened read-only
* *
* Note that with this constructor, you will need to call {@link #close()} * Note that with this constructor, you will need to call {@link #close()}
* when you're done to have the underlying file closed, as the file is * when you're done to have the underlying file closed, as the file is
@ -119,22 +119,71 @@ public class NPOIFSFileSystem extends BlockStore
*/ */
public NPOIFSFileSystem(File file) public NPOIFSFileSystem(File file)
throws IOException throws IOException
{
this(file, true);
}
/**
* Creates a POIFSFileSystem from a <tt>File</tt>. This uses less memory than
* creating from an <tt>InputStream</tt>.
*
* Note that with this constructor, you will need to call {@link #close()}
* when you're done to have the underlying file closed, as the file is
* kept open during normal operation to read the data out.
*
* @param file the File from which to read the data
*
* @exception IOException on errors reading, or on invalid data
*/
public NPOIFSFileSystem(File file, boolean readOnly)
throws IOException
{
this(
(new RandomAccessFile(file, readOnly? "r" : "rw")).getChannel(),
true
);
}
/**
* Creates a POIFSFileSystem from an open <tt>FileChannel</tt>. This uses
* less memory than creating from an <tt>InputStream</tt>.
*
* Note that with this constructor, you will need to call {@link #close()}
* when you're done to have the underlying Channel closed, as the channel is
* kept open during normal operation to read the data out.
*
* @param channel the FileChannel from which to read the data
*
* @exception IOException on errors reading, or on invalid data
*/
public NPOIFSFileSystem(FileChannel channel)
throws IOException
{
this(channel, false);
}
private NPOIFSFileSystem(FileChannel channel, boolean closeChannelOnError)
throws IOException
{ {
this(); this();
// Open the underlying channel try {
FileChannel channel = (new RandomAccessFile(file, "r")).getChannel(); // Get the header
ByteBuffer headerBuffer = ByteBuffer.allocate(POIFSConstants.SMALLER_BIG_BLOCK_SIZE);
// Get the header IOUtils.readFully(channel, headerBuffer);
ByteBuffer headerBuffer = ByteBuffer.allocate(POIFSConstants.SMALLER_BIG_BLOCK_SIZE);
IOUtils.readFully(channel, headerBuffer); // Have the header processed
_header = new HeaderBlock(headerBuffer);
// Have the header processed
_header = new HeaderBlock(headerBuffer); // Now process the various entries
_data = new FileBackedDataSource(channel);
// Now process the various entries readCoreContents();
_data = new FileBackedDataSource(channel); } catch(IOException e) {
readCoreContents(); if(closeChannelOnError) {
channel.close();
}
throw e;
}
} }
/** /**