简体   繁体   English

处理 Java 中的 IO 异常

[英]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 block
        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?也许我被 RAII 宠坏了,但在 Java 中一定有更好的方法来做到这一点,对吧?

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:如果您对IOExceptionFileNotFoundException有相同的异常处理代码,那么您可以只用一个catch子句以更紧凑的方式重写您的示例:

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.如果您可以传播可能比手动打印堆栈跟踪更有意义的异常,您甚至可以摆脱外部try-catch 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 .此外,需要手动关闭 stream 将在 Java 7 中通过自动资源管理得到解决。

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 .除非您想在此级别编写,否则最好创建自己的辅助方法或使用现有的方法,如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 块紧接在一起。

try {
  ...
}
catch (SomeException e) {
  ...
}
catch (OtherException e) {
  ...
}

If you want to do this in plain Java, the code you have posted looks OK.如果您想在普通的 Java 中执行此操作,您发布的代码看起来还可以。

You could use 3rd party libraries such as Commons IO, in which you would need to write much less code.您可以使用 3rd 方库,例如 Commons IO,您需要在其中编写更少的代码。 eg例如

Check out Commons IO at:查看 Commons IO:

http://commons.apache.org/io/description.html 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.当然,这意味着foo的调用者必须处理IOException ,但无论如何大部分时间都应该是这种情况。 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:例如,使用 Apache Commons IO 它将是:

//...
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).要记住的是标准 Java 缺少许多这些小实用程序和每个人都需要的易于使用的界面,因此您必须依赖一些支持库,例如Apache CommonsGoogle Guava ,...在您的项目中,(或实现您的自己的实用程序类)。

Use org.apache.commons.io.FileUtils.readFileToByteArray(File) or something similar from that package.使用org.apache.commons.io.FileUtils.readFileToByteArray(File)或类似 package 的东西。 It still throws IOException but it deals with cleaning up for you.它仍然会抛出 IOException,但它会为您处理清理工作。

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 . Google guava 试图通过引入Closeables来解决这个问题。

Otherwise you have to wait until AutoCloseable from JDK 7 comes out as it addresses some of the cases when IOException is thrown.否则,您必须等到 JDK 7 的AutoCloseable出现,因为它解决了抛出 IOException 的一些情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM