Today few comments on how to deal with Files, Streams, Connections and anything else that is ‘closeable’ in Java. To simplify we will focus on a FileWriter class and a simple code snippet with a bug that uses it:
1: 2: 3: 4: 5: 6: 7: 8: |
public void writeToFile(String fileName, String content) {
try {
FileWriter file = new FileWriter(fileName);
file.write(content);
} catch (IOException e) {
// Log the exception
}
}
|
So what’s wrong? Well, plenty of things: we do not check the input values (maybe they are null or rubbish?), we do not care whether the file existed or is a directory, we do not care about specifying the encoding for the file. On the other hand you could argue that all of this are not problems but ‘features’, that the contract of this method says: just write using a FileWriter. That may be, but still there is one thing wrong with this code – we did not close the file.
Is that important? Well, yeah! Not closing the file may result in corrupted output of your write and makes the system still occupy the resources that could be freed. Always remember to close your Files, Streams, Connections! Let’s make a quick fix to the code and remove the bug:
1: 2: 3: 4: 5: 6: 7: 8: 9: |
public void writeToFile(String fileName, String content) {
try {
FileWriter file = new FileWriter(fileName);
file.write(content);
file.close();
} catch (IOException e) {
// Log the exception
}
}
|
Fixed? I guess some of you think it is fixed, but in fact it is not – what if there is an exception thrown during the write? The method will exit and the file will not be closed! Okay, there is a fix for that – use try/finally clause. This will guarantee that no matter what will happen in write the file will be closed.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: |
public void writeToFile(String fileName, String content) {
FileWriter file = null;
try {
file = new FileWriter(fileName);
file.write(content);
} catch (IOException e) {
// Log the exception
} finally {
file.close();
}
}
|
Fixed? Well… no. The exception can be also thrown in the FileWriter constructor, so in finally block the file will be null. And this will result in NullPointerException. Let’s deal with that:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: |
public void writeToFile(String fileName, String content) {
FileWriter file = null;
try {
file = new FileWriter(fileName);
file.write(content);
} catch (IOException e) {
// Log the exception
} finally {
if (file != null) {
file.close();
}
}
}
|
Done? Not yet… file.close() also can throw an exception! Since the method writeToFile does not allow any checked exception to be thrown, we have to deal with that also:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: |
public void writeToFile(String fileName, String content) {
try {
FileWriter file = new FileWriter(fileName);
try {
file.write(content);
} finally {
file.close();
}
} catch (IOException e) {
// Log the exception
}
}
|
Finally (pun intended) we are done and the bug is fixed! Notice that in this code we did not had to check whether file is null before closing it – this is because the only way file is null is if an exception was thrown in the constructor in line 3 and this would lead to skipping most of the code and going to line 10. As you can see closing a closeable object is not a trivial task, so remember to do it properly!
There is another issue appearing in this problem – readability. If this the code above seems readable to you, then try to imagine dealing with more than one closeable object – it can get really messy! Therefore whenever you work with closeable objects it is a good idea to split the code into 2 methods: one that deals with exceptions and closing and the other which just does the main code. To see how this would work with the code above take a look at the following:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: |
// Here we handle opening the file and manage exceptions.
public void writeToFile(String fileName, String content) {
try {
FileWriter file = new FileWriter(fileName);
try {
performWriteToFile(file, content);
} finally {
file.close();
}
} catch (IOException e) {
// Log the exception
}
}
// Here we perform all the operations on the file.
// This method usually is much longer.
private void performWriteToFile(FileWriter file,
String content) throws IOException {
file.write(content);
}
|
5 Comments until now
try C#’s “using” statement
I prefer to write a simple utility method that closes a closable stream ignoring nulls and exceptions. See also Apaches IOUtils.
FileWriter writer = null;
try {
writer = new FileWriter(fileName);
performWriteToFile(writer, content);
} catch (IOException e) {
// Log the exception
} finally {
closeQuietly(writer);
}
Good explantion dude….!
Thanks
JavaImran
Good catch.
This way we can enhance the readabilty of the code and good exception handling as well.
Thanks for the post.
Women’s vibram five fingers kso shoes Gray Pink Shoes can keep your feet in the freest condition,just as if your were barefooted. vibram five fingers kso shoes is made of the best and proper materials,so you don’t need to doubt of its comfort with so thin sole and upper.
Gray match with a dreamlike and romantic color,pink vibram five fingers kso shoes is very consistent with the style of young girls.In this busy and tense times,people need relax without any fetter.
Add your Comment!