public static String getMD5Checksum(String filePath) throws Exception {
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
return DigestUtils.md5Hex(fis);
}
In the above code fis is not closed but it is not thrown as error in SonarQube. The DigestUtils.md5Hex method does not close the stream too.
Both SonarQube and Sonar Java plugins are in latest versions.
You don't use the FileInputStream, but if you add the following line (or similar):
fis.read();
It will add the valid rule: Resources should be closed (squid:S2095)
Connections, streams, files, and other classes that implement the Closeable interface or its super-interface, AutoCloseable, needs to be closed after use.
But you have a point that we need to release resource as FileInputStream
Yes, you need to close the inputstream if you want your system resources released back.
You can raise this question in SonarSource community
EDIT
Resources should be closed not warns on new FileInputStream added as a possible sonarqube bug
Related
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.
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.
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.
I saw this example, and I didn't see the close() method invoked on the InputStream, so would prop.load() close the stream automatically? Or is there a bug in the example?
The Stream is not closed after Properties.load ()
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(new File("abc.properties"));
new Properties().load(in);
System.out.println(in.read());
}
The above code returns "-1" so the stream is not closed. Otherwise it should have thrown java.io.IOException: Stream Closed
Why do you ask when the javadoc of Properties.load(InputStream inStream) says this?
The specified stream remains open after this method returns.
It has been saying that since Java 6.
As EJP said in a comment: Don't rely on arbitrary Internet junk. Use the official Oracle Java documentation as your primary source of information.
The following try-with-resources will close the InputStream automatically (you can add catch and finally if needed):
try (InputStream is = new FileInputStream("properties.txt")) {
// is will be closed automatically
}
Any resource declared within a try block opening will be closed. Hence, the new construct shields you from having to pair try blocks with corresponding finally blocks that are dedicated to proper resource management.
Article by Oracle here: http://www.oracle.com/technetwork/articles/java/trywithresources-401775.html.
This question already has answers here:
Why doesn't java.io.File have a close method?
(6 answers)
Closed 8 years ago.
After upgrading to Java 7 I get the following code flagged by Eclipse:
try (File file = new File(FILE_NAME)) {
file.delete();
}
Error is:
The resource type File does not implement java.lang.AutoCloseable
And Java's documentation doesn't have File listed in the AutoCloseable docs:
http://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html
So besides adding the catch block, what is the suggested alternative?
As Jeffrey said in the comment to the question, you need to differentiate between a File and an InputStream, e.g. FileInputStream.
There is nothing to close in a File, but there is something to close in a stream or a reader.
try (FileInputStream fs = new FileInputStream (new File(FILE_NAME))) {
// do what you want with the stream
}
I have a parallel question.
let's assume the following method which is running by a thread(A).
void run(){
//some work
FileInputStream fis=new FileInputStream(new File("/home/share/_config"));
//some work with fis
}
and assume there is a error which is not catchable, so as I got from java threading, we can add a uncaught exception manager with setUncaughtExceptionHandler() method, so the question is, how would I access the file I opened (fis) from the killed thread stack and close it from the handler?
NOTE: Code works in Java 7+
Don't do this! Usually, the method that opens a stream should also close it! Put the stream in a try-with-resource clause, then it will be closed automatically:
void run() {
//some work
try (FileInputStream fis=new FileInputStream(new File("/home/share/_config"))) {
//some work with fis
}
}
The stream fis will be closed, if the execution flow leaves the try block - either because it finishes its work or due to an exception.
It is also possible to open multiple input streams in the same try-with-resource clause by using a semicolon (;) as separator. See http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html for details.
Recently I got a comment to this answer that I should stay away from java.io if I want to use "pure NIO".
This is the simplified code (copy a file):
private static void copy(File source, File destination) throws IOException {
long length = source.length();
FileChannel input = new FileInputStream(source).getChannel();
FileChannel output = new FileOutputStream(destination).getChannel();
input.transferTo(0, length, output);
output.close();
input.close();
}
(code extremely simplified: removed try-finally and loop)
My question is how to get a FileChannel or other NIO class for reading a file without using java.io (FileInputStream)?
EDIT:
Java 6 (or before only)
Java 6 only has FileInputStream.getChannel(), FileOutputStream.getChannel(), and RandomAccessFile.getChannel()
Java 7 has java.nio.channels.FileChannel.open(...) and java.nio.Files.newByteChannel(...)
The javadoc of FileChannel says:
This class does not define methods for opening existing files or for creating new ones; such methods may be added in a future release. In this release a file channel can be obtained from an existing FileInputStream, FileOutputStream, or RandomAccessFile object by invoking that object's getChannel method, which returns a file channel that is connected to the same underlying file.
That is, with java 1.6 you can't get a FileChannel without using old java.io.