Bug 52204

Summary: InputStream not closed
Product: POI Reporter: Samuel Imbert <samuel.imbert>
Component: XSSFAssignee: POI Developers List <dev>
Status: RESOLVED WONTFIX    
Severity: normal    
Priority: P2    
Version: 3.7-FINAL   
Target Milestone: ---   
Hardware: PC   
OS: All   

Description Samuel Imbert 2011-11-17 12:50:15 UTC
When we create a XSSFWorkbook with the following code : new XSSFWorkbook(fileName)
the InputStream seems not closed.

Indeed next we can't modify the file (error : file use by System).

If I do : 

File f = new File(fileName);
InputStream in = new FileInputStream(f);                    
XSSFWorkbook wb = new XSSFWorkbook(in);
in.close();

The error doesn't appear anymore.

Is it a bug or my bad use of XXSF API?
Comment 1 Nick Burch 2011-11-17 12:52:58 UTC
What leads you to believe that something is still open when you call the filename based XSSF constructor?
Comment 2 Samuel Imbert 2011-11-17 14:07:46 UTC
(In reply to comment #1)
> What leads you to believe that something is still open when you call the
> filename based XSSF constructor?

As i said, after i used this constructor, i'm not able to modify the file.

If i use the other constructor, i'm able to modify it. 

So i assume it's beacause of the constructor who didn't close his access to the file. 

NB : I'm using the POI library in a facelet J2E project.
Comment 3 Yegor Kozlov 2011-11-18 12:50:09 UTC
It is not a bug, rather a feature of the XSSF API. 

In short, .xlsx file is a zip archive and there are two ways to open it:

1) from file which leads to invoking java.util.zip.ZipFile(File file) deep in POI internals. 

2) from input stream in which case we first read everything into memory and then pass the data to ZipInputStream  

It should be noted, that (2) uses quite a bit more memory than (1), which
doesn't need to hold the whole zip file in memory, and can take advantage
of native methods. 

As you may guessed, (1) opens the underlying zip but does not close it which results in a leak.

You have two choices:

 choice 1: open from FileInputStream
 choice 2: re-write your code as follows:

OPCPackage pkg = OPCPackage.open(file);
XSSFWorkbook wb = new XSSFWorkbook(pkg);

// work with workbook

pkg.close(); // gracefully closes the underlying zip file

I'm going to update the documentation to reflect this feature.

Regards,
Yegor
Comment 4 Samuel Imbert 2011-11-18 13:17:18 UTC
Ok, thanks Yegor!

I tested the execution time of both algorithm and your code with OPCPackage is faster than with InputStream.

So it's fine for me!

Have a nice day.