1

I have the following code to open a zip file that contains several files, and extracts information from each file:

public static void unzipFile(InputStream zippedFile) throws IOException {
  try (ZipInputStream zipInputStream = new ZipInputStream(zippedFile)) {
    for (ZipEntry zipEntry = zipInputStream.getNextEntry(); zipEntry != null; zipEntry = zipInputStream.getNextEntry()) {
      BufferedReader reader = new BufferedReader(new InputStreamReader(new BoundedInputStream(zipInputStream, 1024)));
      //Extract info procedure...
    } 
  }
}

In summary, I pick each file from the zip, and open it with a BufferedReader to read the information from it. I'm also using BoundedInputStream (org.apache.commons.io.input.BoundedInputStream) to limit buffer size and avoid unwanted huge lines on the files.

It works as expected, however I'm getting this warning on Sonar:

Use try-with-resources or close this "BufferedReader" in a "finally" clause.

I just can't close (or use try-with-resources, like I did on the beginning of the method) the BufferedReaders I create - if I call the close method, the ZipInputStream will close. And the ZipInputStream is already under try-with-resources...

This sonar notification is marked as critical, but I believe it is a false positive. I wonder if you could clarify to me - am I correct, or should I handle this in a different way? I don't want to leave resource leaks in the code, since this method will be called several times and a leak could cause a serious damage.

Leonardo Alves Machado
  • 2,747
  • 10
  • 38
  • 53

2 Answers2

1

The sonar notification is correct in that there is technically a resource leak that could eat up resources over time (see garbage collection and IO classes). In order to avoid closing the underlying ZipInputStream, consider passing the ZipEntry into the BoundedInputStream in the for loop as per this SO question: reading files in a zip file. Thus, when the BufferedReader is closed, the BoundedInputStream is closed and not the ZipInputStream.

Coby Z
  • 63
  • 1
  • 5
  • I don't have a `ZipFile` like the question you linked. – Leonardo Alves Machado Apr 26 '19 at 20:46
  • There's no need for a `ZipFile`, the point of linking that answer was to highlight that an input stream can be created from a `ZipEntry`, so it would be possible to layer a `BufferedReader` on top of it and close said reader without closing the `ZipInputStream` that provides the entries. – Coby Z Apr 27 '19 at 17:58
1

Thanks to the answers here, I could address my issue this way:

BoundedInputStream boundedInputStream = new BoundedInputStream(zipInputStream, MAX_LINE_SIZE_BYTES);
boundedInputStream.setPropagateClose(false);

try(BufferedReader reader = new BufferedReader(new InputStreamReader(boundedInputStream))) { ...

With boundedInputStream.setPropagateClose(false); I can close the BufferedReader without closing the zipInputStream.

Leonardo Alves Machado
  • 2,747
  • 10
  • 38
  • 53