A beginners book on Java has the following code in it. This book also explains about exceptions very well, and since I understood how exception works, I got a question about the following code.
For some reason if FileWriter class throws an exception, writer.close() wouldn't be executed. Therefore I think the best place to close the writer object is in a finally block. Even prior to this I have seen many code written like this, where the resource will be closed in the try block itself. I think there is no point in doing so. Only when there is no exception the resource will be closed.
Am I wrong? What is the best way to close resources in java. Should we never write code like the following?
public static void main(String[] args) {
try{
FileWriter writer = new FileWriter("file.txt");
writer.write("i am writing");
writer.close();
}catch(IOException e){
ex.printStackTrace();
}
}
I agree with #cyber-rookie, it is probably best to close resources in a finally block.
Java 7 introduced "try-with-resources" in order to cut down on programming mistakes...
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
You can now write...
try (FileWriter writer = new FileWriter("file.txt")) {
writer.write("i am writing");
} catch (IOException e) {
e.printStackTrace();
}
The compiler will add the extra code to close the writer at the end of the block for you
If your are using Java 7, the best approach is to use try with resource. See https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
try (FileWriter writer = new FileWriter("file.txt")) {
writer.write("i am writing");
}
you are right, resource should be closed in finally block.
as of java 7 you can use try-with-resource also as :
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly if these resources implements AutoCloseable interface.
In my experience we would utilise the finally clause of a try-catch:
public static void main(String[] args) {
FileWriter writer = null;
try {
writer = new FileWriter("file.txt");
writer.write("i am writing");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
PS: Place this in separate method and throw the exception, let the class using this handle exceptions.
Answer to a comment to add multiple resources in a try with resource block:
try(FileWriter writer = new FileWriter("file.txt"); BufferedReader reader = new BufferedReader(new FileReader("file.txt"))){
// you can put many AUTOCLOSEABLE objects in try with resource. Just seperate them with ";"
} catch (IOException e) {
e.printStackTrace();
}
At work (Java 6), we close the resources in the TRY block then also do a defensive close in the FINALLY block.
BufferedReader bufferedReader;
try {
//initialize and do something with the bufferedReader
bufferedReader.close();
} catch (FileNotFoundException ex) {
// notify the user
} catch (IOException ex) {
// notify the user
} finally {
if (bufferedReader != null) {
try {
//defensive close
bufferedReader.close();
} catch (IOException ex) {
// this will be thrown if bufferedReader is already closed (in Try block, so can be leave to blank
}
}
}
Related
Code Snippet :
InputStream inputStream = null;
try{
ExternalServiceObject object = externalService.getObject();
inputStream = object.getInputStream();
// further uses of inputStream
} catch(Exception e){
throw e;
} finally {
if(inputStream != null)
inputStream.close();
}
Here, externalService.getObject() can also throw an exception.
Wish to refactor this code using try-with-resources, hence avoiding the finally block.
Or is the current behavior the most appropriate behavior.
All the comments and answers are appreciated.
If you don't need the external service object for anything else:
try (InputStream inputStream = externalService.getObject().getInputStream()) {
// further uses of inputStream
} catch (Exception e) {
// ... logging etc
throw e;
}
I believe that execution order in the try-with-resources is top-down
(like all other java variable definitions)
try
(
ExternalServiceObject externalServiceObject = externalService.getObject(),
InputStream inputStream = externalServiceObject.getInputStream();
)
{
// further uses of inputStream
}
catch (Exception e)
{
// do stuff.
}
Caveat: ExternalServiceObject must implement AutoCloseable
So, use try-with-resources if that's what you want to use:
try {
ExternalServiceObject object = externalService.getObject();
try (InputStream inputStream = object.getInputStream()) {
// ...
}
} catch (Exception e) {
throw e; // But why catch it only to rethrow?
}
The closing of the InputStream can be done using a try-with-resources block. It is more readable and less clunky. InputStream implements AutoCloseable and thus upon exiting a try-with-resources block the class's close method will automatically be called. If you are only using the InputStream for the scope of the try-catch-finally block then you should move it to the try block.
Also, you should avoid (where possible) catching Exception. Any resulting exceptions that are thrown in your try block could result in unwanted behavior.
I would like to make you think about a tiny problem using the method printStackTrace(PrintWriter s). I need to use it in append mode.
The following example is explaining what I mean:
try {
} catch (Exception e) {
try {
e.printStackTrace(new PrintWriter(new FileWriter("mylog.txt", true)));
} catch (IOException ioe) {
System.out.println("I can't open the file mylog.txt");
}
}
Note that
new FileWriter("mylog.txt", true);
is the way I open the file (and create it the first time because it doesn't exist) in append mode.
The result is that in the file there is only the last exception and not a series of exceptions. One time it occurred that the method opened the file in which it didn't write anything.
How can I solve this problem?
Thank you.
Adding to what krzyk mentioned
Per OutputStreamWriter.close() : Closes the stream, flushing it first. Once the stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously closed stream has no effect.
As mentioned, if you do not call close and this try{}catch is getting fired frequently, you are not flushing content to file.
It should written like
try {
} catch (Exception e) {
try {
FileWriter fw = new FileWriter("mylog.txt", true)
e.printStackTrace(new PrintWriter(fw));
fw.close();
} catch (IOException ioe) {
System.out.println("I can't open the file mylog.txt");
}
}
A better approach will be
FileWriter fw = new FileWriter("mylog.txt", true);
PrintWriter pw = new PrintWriter(fw);
try {
} catch (Exception e) {
try {
e.printStackTrace(pw);
} catch (IOException ioe) {
System.out.println("I can't open the file mylog.txt");
}
}finally {
pw.close();
fw.close();
}
You should close the created Writers, not closing it might cause the problems you describe.
try (PrintWriter writer = new PrintWriter(new FileWriter("mylog.txt", true))) {
e.printStackTrace(writer);
}
I submitted my code for Veraocode Security Testing tool and i got this Improper Resource Shutdown or Release at the below code:
//This function is used to print trace in the in the LogFile for debugging purpose
PrintWriter f;
try {
f = new PrintWriter(new BufferedWriter(new FileWriter(fileName,true)));//issue at this line
synchronized(this) {
f.println(new StringBuffer(dateString).append("<").append(Thread.currentThread().getName()).append(">").append(traceLog).toString());
}
f.close();
checkFileSize();
}catch(IOException e){
e.printStackTrace();
}
Someone please help me on this...
You need to close your PrintWriter.
f.close();
try {
f = new PrintWriter(new BufferedWriter(new FileWriter(fileName,true)));//issue at this line
synchronized(this) {
f.println(new StringBuffer(dateString).append("<").append(Thread.currentThread().getName()).append(">").append(traceLog).toString());
}
checkFileSize();
}catch(IOException e){
e.printStackTrace();
} finally {
if (f != null) {
f.close();
}
}
Resources should be closed in finally clause. So that they definitely get executed. Because if you put closing code in try, and some exception occurs before the closing line. The resource doesn't get closed properly.
Also if you are using JDK-7, have a look at try-with-resources.
You need to close the PrintWriter in catch block also Or create finally block and close the resource.
}catch(IOException e){
e.printStackTrace();
f.close();
}
OR
finally {
if (f != null) {
f.close();
}
}
I regularly see this style of resource clean-up:
InputStream in = null;
try {
in = new FileInputStream(file);
// ...
} finally {
if (in != null) {
in.close();
}
}
I have always used the following style:
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
But am I missing something? Is there an advantage to the former that I'm not seeing?
I suspect its to avoid having two nested try/catch blocks instead of one.
InputStream in = null;
try {
in = new FileInputStream(file);
// ...
} catch(IOException ioe) {
// handle exception.
} finally {
IOUtils.closeQuietly(in);
}
The second case is incomplete.
try {
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
} catch(IOException e) {
// handle exception
}
If you have multiple files, this could get really messy.
Suppose that in the first example you have some other code before defining in that gets you out of the try block. If you get to the finally without in been defined you will get a NullPointerException when trying to close it. So you will have to make the check to avoid errors like that.
This is very simple example, And may not create a problem as you are creating InputStream in same bloke. But if InputStream is closed because of some Exception or other fault, in that case your code will fail, So its always better to check if InputStream is available
The second one will not compile since the constructor of FileInputStream can throw a FileNotFoundException, thus you'd need an extra try-catch block, unless of course, the method itself throws it.
Another common idiom is to write a closeQuietly() method to avoid having to write the if (is != null) check all over your finally blocks. This is what Apache Common's IOUtils does:
public static void closeQuietly(InputStream input) {
try {
if (input != null) {
input.close();
}
} catch (IOException ioe) {
// ignore
}
}
Also note that since Java 7, you can use the following:
try (InputStream is = new FileInputStream(file)) {
} catch (final FileNotFoundException | IOException ex) {
}
The null check here for the InputStream is necessary as it is possible that the variable might not be assigned. In this case a NullPointerException would be thrown when attempting to close it when calling:
in.close();
In the 2nd block outside of the try/catch block:
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
You can easily encounter other exceptions before entering the block and the InputStream is never closed.
Lets say you need to open not one, but two files. You would do
final InputStream in = new FileInputStream(file1);
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
in.close();
}
If the out fails to open, you will get an exception and because it's out of the try block in won't be closed in the finally block.
In the other method:
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
if (out != null) out.close();
if (in != null) in.close();
}
If out fails to open, you will go to the finally block and close both streams. If in fails to open, you will go to the finally block, and free only in - because out==null.
edit
As the aetheria mentioned, that code wouldn't work because close() throws exception in Java. It can easily be fixed by putting each resource release in it's own try-catch block:
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
try{ out.close(); }catch(Exception e){}
try{ in.close(); }catch(Exception e){}
}
I ditched the null checking - if in or out is null, it'll throw a NullPointerException that will be ignored. And the reason I ignore close exceptions is that disposal methods shouldn't throw exceptions in the first place. If handling closing exceptions is required, you can always close the streams again, after the finally block. That way, any stream that can be closed will be closed already(so you wouldn't have to worry about it), and you can handle any exceptions from close more elegantly.
Now, aetheria also suggested to put a separate try-finally block for each resource that would look like this:
final InputStream in = new FileInputStream(file1);
try {
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
}
} finally {
in.close();
}
This works, but even with only two resources, it's much less elegant, as it splits the allocations and releasing code, making it harder to keep track of it(in my opinion, at least).
The standard way of handling file reading and writing in java goes something like this:
try
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("file.dat"));
oos.writeObject(h);
oos.close();
}
catch (FileNotFoundException ex)
{
}
catch (IOException ex)
{
}
But I'm bothered by that code, because it could be possible here that the file is never closed if an exception is thrown. Sure we could add a finally clause and initialise the ObjectOutputStream outside the try block. However, when you do that you need to add another try/catch block INSIDE the finally block again...that's just ugly. Is there a better way of handling this problem?
use apache commons io
http://commons.apache.org/proper/commons-io/
look at their FileUtils class. Full of gold. Gold I say....
This is not the standard way at all. This is the bad way.
The way I use most of the time is this one :
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new FileOutputStream("file.dat"));
// use out
}
finally {
if (out != null) {
try {
out.close();
}
catch (IOException e) {
// nothing to do here except log the exception
}
}
}
The code in the finally block can be put in a helper method, or you can use commons IO to close the stream quietly, as noted in other answers.
A stream must always be closed in a finally block.
Note that JDK7 will make it much easier with the new syntax, which will automatically close the stream at the end of the try block :
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file.dat"))) {
// use out
}
This why I use commons-io's IOUtils.closeQuitely(...)
try
{
...
}
finally
{
IOUtils.closeQuietly(costream);
}
try
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("file.dat"));
oos.writeObject(h);
//oos.close(); // glow coder removed
}
catch (FileNotFoundException ex)
{
}
catch (IOException ex)
{
}
// glowcoder adds:
finally {
try {
oos.close();
}
catch(IOException ex) {
// dammit we tried!
}
}
add this finally:
finally{
if(oos != null)
oos.close();
}