mirror of
https://github.com/apache/poi.git
synced 2026-02-27 20:40:08 +08:00
[bug-67579] add new XSSFWorkbook constructor
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1913359 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ff5fc9d582
commit
e94b284c59
@ -43,20 +43,25 @@ import org.apache.poi.util.Removal;
|
||||
*/
|
||||
public final class PackageHelper {
|
||||
|
||||
public static OPCPackage open(InputStream is) throws IOException {
|
||||
return open(is, false);
|
||||
/**
|
||||
* @param stream The InputStream to read from - which is closed when it is read
|
||||
* @return OPCPackage
|
||||
* @throws IOException If reading data from the stream fails
|
||||
*/
|
||||
public static OPCPackage open(InputStream stream) throws IOException {
|
||||
return open(stream, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stream The InputStream to read from
|
||||
* @param closeStream whether to close the stream (default is false)
|
||||
* @since POI 5.2.0
|
||||
* @param closeStream whether to close the stream
|
||||
* @return OPCPackage
|
||||
* @throws IOException If reading data from the stream fails
|
||||
* @since POI 5.2.0
|
||||
*/
|
||||
public static OPCPackage open(InputStream stream, boolean closeStream) throws IOException {
|
||||
try {
|
||||
return OPCPackage.open(stream);
|
||||
return OPCPackage.open(stream, closeStream);
|
||||
} catch (InvalidFormatException e){
|
||||
throw new POIXMLException(e);
|
||||
} finally {
|
||||
|
||||
@ -328,6 +328,38 @@ public abstract class OPCPackage implements RelationshipSource, Closeable {
|
||||
return pack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a package.
|
||||
*
|
||||
* Note - uses quite a bit more memory than {@link #open(String)}, which
|
||||
* doesn't need to hold the whole zip file in memory, and can take advantage
|
||||
* of native methods
|
||||
*
|
||||
* @param in
|
||||
* The InputStream to read the package from.
|
||||
* @param closeStream
|
||||
* Whether to close the input stream.
|
||||
* @return A PackageBase object
|
||||
*
|
||||
* @throws InvalidFormatException
|
||||
* Throws if the specified file exist and is not valid.
|
||||
* @throws IOException If reading the stream fails
|
||||
* @since POI 5.2.5
|
||||
*/
|
||||
public static OPCPackage open(InputStream in, boolean closeStream) throws InvalidFormatException,
|
||||
IOException {
|
||||
OPCPackage pack = new ZipPackage(in, PackageAccess.READ_WRITE, closeStream);
|
||||
try {
|
||||
if (pack.partList == null) {
|
||||
pack.getParts();
|
||||
}
|
||||
} catch (InvalidFormatException | RuntimeException e) {
|
||||
IOUtils.closeQuietly(pack);
|
||||
throw e;
|
||||
}
|
||||
return pack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a package if it exists, else it creates one.
|
||||
*
|
||||
|
||||
@ -115,7 +115,7 @@ public final class ZipPackage extends OPCPackage {
|
||||
|
||||
/**
|
||||
* Constructor. Opens a Zip based Open XML document from
|
||||
* an InputStream.
|
||||
* an InputStream. The InputStream is closed.
|
||||
*
|
||||
* @param in
|
||||
* Zip input stream to load.
|
||||
@ -134,6 +134,30 @@ public final class ZipPackage extends OPCPackage {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Opens a Zip based Open XML document from
|
||||
* an InputStream. The InputStream is closed.
|
||||
*
|
||||
* @param in
|
||||
* Zip input stream to load.
|
||||
* @param access
|
||||
* The package access mode.
|
||||
* @param closeStream
|
||||
* Whether to close the input stream.
|
||||
* @throws IllegalArgumentException
|
||||
* If the specified input stream is not an instance of
|
||||
* ZipInputStream.
|
||||
* @throws IOException
|
||||
* if input stream cannot be opened, read, or closed
|
||||
* @since POI 5.2.5
|
||||
*/
|
||||
ZipPackage(InputStream in, PackageAccess access, boolean closeStream) throws IOException {
|
||||
super(access);
|
||||
try (ZipArchiveThresholdInputStream zis = ZipHelper.openZipStream(in, closeStream)) {
|
||||
this.zipArchive = new ZipInputStreamZipEntrySource(zis);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Opens a Zip based Open XML document from a file.
|
||||
*
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.openxml4j.opc.internal;
|
||||
|
||||
import org.apache.poi.util.Internal;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Internal
|
||||
final class NoCloseInputStream extends FilterInputStream {
|
||||
NoCloseInputStream(InputStream stream) {
|
||||
super(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
}
|
||||
@ -163,20 +163,33 @@ public final class ZipHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the specified stream as a secure zip
|
||||
* Opens the specified stream as a secure zip. Closes the Input Stream.
|
||||
*
|
||||
* @param stream
|
||||
* The stream to open.
|
||||
* @param stream The stream to open.
|
||||
* @return The zip stream freshly open.
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
public static ZipArchiveThresholdInputStream openZipStream(InputStream stream) throws IOException {
|
||||
return openZipStream(stream, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the specified stream as a secure zip. Closes the Input Stream.
|
||||
*
|
||||
* @param stream The stream to open.
|
||||
* @param closeStream whether to close the stream
|
||||
* @return The zip stream freshly open.
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
public static ZipArchiveThresholdInputStream openZipStream(
|
||||
final InputStream stream, final boolean closeStream) throws IOException {
|
||||
// Peek at the first few bytes to sanity check
|
||||
InputStream checkedStream = FileMagic.prepareToCheckMagic(stream);
|
||||
verifyZipHeader(checkedStream);
|
||||
|
||||
|
||||
final InputStream processStream = closeStream ? checkedStream : new NoCloseInputStream(checkedStream);
|
||||
// Open as a proper zip stream
|
||||
return new ZipArchiveThresholdInputStream(new ZipArchiveInputStream(checkedStream));
|
||||
return new ZipArchiveThresholdInputStream(new ZipArchiveInputStream(processStream));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -277,17 +277,40 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
|
||||
* pkg.close(); // gracefully closes the underlying zip file
|
||||
* }</pre>
|
||||
*
|
||||
* @param stream The InputStream, which is closed when it is read.
|
||||
* @throws IOException If reading data from the stream fails
|
||||
* @throws POIXMLException a RuntimeException that can be caused by invalid OOXML data
|
||||
* @throws IllegalStateException a number of other runtime exceptions can be thrown, especially if there are problems with the
|
||||
* input format
|
||||
*/
|
||||
public XSSFWorkbook(InputStream is) throws IOException {
|
||||
this(is, false);
|
||||
public XSSFWorkbook(InputStream stream) throws IOException {
|
||||
this(stream, true);
|
||||
}
|
||||
|
||||
private XSSFWorkbook(InputStream is, boolean closeStream) throws IOException {
|
||||
this(PackageHelper.open(is, closeStream));
|
||||
/**
|
||||
* Constructs a XSSFWorkbook object, by buffering the whole stream into memory
|
||||
* and then opening an {@link OPCPackage} object for it.
|
||||
*
|
||||
* <p>Using an {@link InputStream} requires more memory than using a File, so
|
||||
* if a {@link File} is available then you should instead do something like
|
||||
* <pre>{@code
|
||||
* OPCPackage pkg = OPCPackage.open(path);
|
||||
* XSSFWorkbook wb = new XSSFWorkbook(pkg);
|
||||
* // work with the wb object
|
||||
* ......
|
||||
* pkg.close(); // gracefully closes the underlying zip file
|
||||
* }</pre>
|
||||
*
|
||||
* @param stream The InputStream.
|
||||
* @param closeStream Whether to close the stream.
|
||||
* @throws IOException If reading data from the stream fails
|
||||
* @throws POIXMLException a RuntimeException that can be caused by invalid OOXML data
|
||||
* @throws IllegalStateException a number of other runtime exceptions can be thrown, especially if there are problems with the
|
||||
* input format
|
||||
* @since POI 5.2.5
|
||||
*/
|
||||
public XSSFWorkbook(InputStream stream, boolean closeStream) throws IOException {
|
||||
this(PackageHelper.open(stream, closeStream));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1460,13 +1460,17 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
|
||||
}
|
||||
}
|
||||
|
||||
static class NoCloseInputStream extends FilterInputStream {
|
||||
NoCloseInputStream(InputStream stream) {
|
||||
super(stream);
|
||||
@Test
|
||||
void testWorkbookCloseCanBeStoppedFromClosingInputStream() throws Exception {
|
||||
try (WrappedStream stream = new WrappedStream(
|
||||
HSSFTestDataSamples.openSampleFileStream("github-321.xlsx"))) {
|
||||
// uses new constructor, available since POI 5.2.5
|
||||
try (XSSFWorkbook wb = new XSSFWorkbook(stream, false)) {
|
||||
XSSFSheet xssfSheet = wb.getSheetAt(0);
|
||||
assertNotNull(xssfSheet);
|
||||
}
|
||||
assertFalse(stream.isClosed(), "stream should not be closed by XSSFWorkbook");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1494,9 +1498,8 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
|
||||
try (ZipArchiveInputStream zis = new ZipArchiveInputStream(Files.newInputStream(tempFile.toPath()))) {
|
||||
ZipArchiveEntry entry;
|
||||
while ((entry = zis.getNextZipEntry()) != null) {
|
||||
// NoCloseInputStream is needed to stop XSSFWorkbook closing the underlying InputStream
|
||||
// this might not sound great but POI has worked like this for years and we can't just change it
|
||||
XSSFWorkbook wb = new XSSFWorkbook(new NoCloseInputStream(zis));
|
||||
// Since POI 5.2.5, you can stop XSSFWorkbook closing the InputStream by using this new constructor
|
||||
XSSFWorkbook wb = new XSSFWorkbook(zis, false);
|
||||
assertNotNull(wb);
|
||||
count++;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user