Handling IO exceptions in Java
Basically, I want to open a file, read some bytes, and then close the file. This is what I came up with:
try
{
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
try
{
// ...
inputStream.read(buffer);
// ...
}
catch (IOException e)
{
// TODO Auto-generated catch bl开发者_C百科ock
e.printStackTrace();
}
finally
{
try
{
inputStream.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Maybe I'm spoiled by RAII, but there must be a better way to do this in Java, right?
If you have the same exception handling code for IOException
and FileNotFoundException
then you can rewrite your example in a more compact way with only one catch
clause:
try {
InputStream input = new BufferedInputStream(new FileInputStream(file));
try {
// ...
input.read(buffer);
// ...
}
finally {
input.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
You can even get rid of the outer try-catch
if you can propagate the exception which probably makes more sense then manually printing the stack trace. If you don't catch some exception in your program you'll get stack trace printed for you automatically.
Also the need to manually close the stream will be addressed in Java 7 with automatic resource management.
With automatic resource management and exception propagation the code reduces to the following:
try (InputStream input = new BufferedInputStream(new FileInputStream(file))) {
// ...
input.read(buffer);
// ...
}
Usually these methods are wrapped up in libraries. Unless you want to write at this level, it is best to create your own helper methods or use existing ones like FileUtils.
String fileAsString = Fileutils.readFileToString(filename);
// OR
for(String line: FileUtils.readLines(filename)) {
// do something with each line.
}
I don't know if it is the right way, but you can have all your code in the same try block, and then have the different catch blocks right after each other.
try {
...
}
catch (SomeException e) {
...
}
catch (OtherException e) {
...
}
If you want to do this in plain Java, the code you have posted looks OK.
You could use 3rd party libraries such as Commons IO, in which you would need to write much less code. e.g.
Check out Commons IO at:
http://commons.apache.org/io/description.html
Sometimes you can reduce the code to the following:
public void foo(String name) throws IOException {
InputStream in = null;
try {
in = new FileInputStream(name);
in.read();
// whatever
} finally {
if(in != null) {
in.close();
}
}
}
Of course this means the caller of foo
has to handle the IOException
but this should be the case most of the time anyway. In the end you don't really reduce all that much complexity but the code becomes much more readable due to less nested exception handlers.
My take on this without using utilities would be:
InputStream inputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
// ...
inputStream.read(buffer);
// ...
} catch (IOException e) {
e.printStackTrace();
throw e; // Rethrow if you cannot handle the exception
} finally {
if (inputStream != null) {
inputStream.close();
}
}
Not a one-liner, but not pretty bad. Using, say, Apache Commons IO it would be:
//...
buffer = FileUtils.readFileToByteArray(file);
//...
The thing to rembember is that standard Java lacks many of these little utilities and easy to use interfaces that everyone needs, so you have to rely on some support libraries like Apache Commons, Google Guava, ... in your projects, (or implement your own utility classes).
Use org.apache.commons.io.FileUtils.readFileToByteArray(File)
or something similar from that package. It still throws IOException but it deals with cleaning up for you.
Try the following:
try
{
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
byte[] buffer = new byte[1024];
try
{
// ...
int bytesRead = 0;
while ((bytesRead = inputStream.read(buffer)) != -1) {
//Process the chunk of bytes read
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
inputStream.close();
}
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Google guava has tried to address this problem by introducing Closeables.
Otherwise you have to wait until AutoCloseable from JDK 7 comes out as it addresses some of the cases when IOException is thrown.
精彩评论