diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java b/poi/src/main/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
index ebee94394b..1a625f38d0 100644
--- a/poi/src/main/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
+++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
@@ -164,7 +164,7 @@ public class POIFSFileSystem extends BlockStore
*/
public POIFSFileSystem(File file, boolean readOnly)
throws IOException {
- this(null, file, readOnly, true);
+ this(null, file, readOnly, true, true);
}
/**
@@ -198,12 +198,33 @@ public class POIFSFileSystem extends BlockStore
*/
public POIFSFileSystem(FileChannel channel, boolean readOnly)
throws IOException {
- this(channel, null, readOnly, false);
+ this(channel, null, readOnly, false, true);
+ }
+
+ /**
+ *
Creates a POIFSFileSystem from an open FileChannel. This uses
+ * less memory than creating from an InputStream.
+ *
+ * Note that with this constructor, you will need to call {@link #close()}
+ * when you're done to have the underlying resources closed. The closeChannel
+ * parameter controls whether the provided channel is closed.
+ *
+ * @param channel the FileChannel from which to read or read/write the data
+ * @param readOnly whether the POIFileSystem will only be used in read-only mode
+ * @param closeChannel whether the provided FileChannel should be closed when
+ * {@link #close()} is called, or when this constructor throws
+ * an exception
+ * @throws IOException on errors reading, or on invalid data
+ * @since POI 5.1.0
+ */
+ public POIFSFileSystem(FileChannel channel, boolean readOnly, boolean closeChannel)
+ throws IOException {
+ this(channel, null, readOnly, closeChannel, closeChannel);
}
@SuppressWarnings("java:S2095")
- private POIFSFileSystem(FileChannel channel, File srcFile, boolean readOnly, boolean closeChannelOnError)
- throws IOException {
+ private POIFSFileSystem(FileChannel channel, File srcFile, boolean readOnly, boolean closeChannelOnError,
+ boolean closeChannelOnClose) throws IOException {
this(false);
try {
@@ -216,7 +237,7 @@ public class POIFSFileSystem extends BlockStore
channel = d.getChannel();
_data = d;
} else {
- _data = new FileBackedDataSource(channel, readOnly);
+ _data = new FileBackedDataSource(channel, readOnly, closeChannelOnClose);
}
// Get the header
diff --git a/poi/src/main/java/org/apache/poi/poifs/nio/FileBackedDataSource.java b/poi/src/main/java/org/apache/poi/poifs/nio/FileBackedDataSource.java
index e3001f238f..31e439fb5d 100644
--- a/poi/src/main/java/org/apache/poi/poifs/nio/FileBackedDataSource.java
+++ b/poi/src/main/java/org/apache/poi/poifs/nio/FileBackedDataSource.java
@@ -43,6 +43,7 @@ public class FileBackedDataSource extends DataSource implements Closeable {
private Long channelSize;
private final boolean writable;
+ private final boolean closeChannelOnClose;
// remember file base, which needs to be closed too
private final RandomAccessFile srcFile;
@@ -64,19 +65,28 @@ public class FileBackedDataSource extends DataSource implements Closeable {
}
public FileBackedDataSource(RandomAccessFile srcFile, boolean readOnly) {
- this(srcFile, srcFile.getChannel(), readOnly);
+ this(srcFile, srcFile.getChannel(), readOnly, false);
}
public FileBackedDataSource(FileChannel channel, boolean readOnly) {
- this(null, channel, readOnly);
+ this(channel, readOnly, true);
}
- private FileBackedDataSource(RandomAccessFile srcFile, FileChannel channel, boolean readOnly) {
+ /**
+ * @since POI 5.1.0
+ */
+ public FileBackedDataSource(FileChannel channel, boolean readOnly, boolean closeChannelOnClose) {
+ this(null, channel, readOnly, closeChannelOnClose);
+ }
+
+ private FileBackedDataSource(RandomAccessFile srcFile, FileChannel channel, boolean readOnly, boolean closeChannelOnClose) {
this.srcFile = srcFile;
this.channel = channel;
this.writable = !readOnly;
+ this.closeChannelOnClose = closeChannelOnClose;
}
+
public boolean isWriteable() {
return this.writable;
}
@@ -170,7 +180,7 @@ public class FileBackedDataSource extends DataSource implements Closeable {
if (srcFile != null) {
// see http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4796385
srcFile.close();
- } else {
+ } else if (closeChannelOnClose) {
channel.close();
}
}