Reputation: 18614
I have a helper class with a static method that returns a stream:
public static InputStream getDocument(File file) throws IOException {
ZipFile zipFile = new ZipFile(file);
return zipFile.getInputStream(zipFile.getEntry("entry"));
}
Another class accesses that method and uses that returned stream:
InputStream is = MyClass.getDocument(new File(str));
My code works.
However, according to the Java Documentation, I should close my resource:
A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement.
But, when I implement try-with-resources
:
public static InputStream getDocument(File file) throws IOException {
try (ZipFile zipFile = new ZipFile(file);) {
return zipFile.getInputStream(zipFile.getEntry("entry"));
}
}
or try-finally
:
public static InputStream getDocument(File file) throws IOException {
InputStream is = null;
try {
ZipFile zipFile = new ZipFile(docx);
is = zipFile.getInputStream(zipFile.getEntry("entry"));
return is;
} finally {
is.close();
}
}
I get an exception:
java.io.IOException: Stream closed
How to make sure, that resource will be closed, after its use?
Upvotes: 1
Views: 1515
Reputation: 10695
try-with-resources does implicitly the same as your second approach with finally
. There is no way to close the zipFile but return an inputStream based on this zipFile.
Generally it would be better to avoid this helper method and use a single try-with-resourrces with multiple resources:
try (
ZipFile zipFile = new ZipFile(file);
inputStream inputStream = zipFile.getInputStream(zipFile.getEntry("entry"));
) {
// Do stuff
} // Both zipFile and inputStream closed here implicitly
If you need to create such a method, you can however make sure that when the stream is closed, the zipFile object also gets closed.
From a related question Does a ZipEntry persist after a ZipFile is closed?
zipFile = new ZipFile(file);
InputStream zipInputStream = ...
return new InputStream() {
@Override
public int read() throws IOException {
return zipInputStream.read();
}
@Override
public void close() throws IOException {
// Better add try/catch around each close()
zipInputStream.close();
zipFile.close();
}
}
That way, when the calling method closes the stream it receives, the zip file would also be closed.
Upvotes: 0
Reputation: 4878
Usually the caller is responsible to close/release the resources.
You can use the try-with-resource or the try-finally construct outside the method as follows:
try (InputStream is = getDocument(aFile) {
//… do your stuff
}
If I can give you an advice, write it in the method documentation:
/**
* The caller is required to close the returned {@link InputStream}
*/
public static InputStream getDocument(File file) throws IOException
Upvotes: 3