14

基本上,我想打开一个文件,读取一些字节,然后关闭该文件。这就是我想出的:

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();
}

也许我被 RAII 宠坏了,但在 Java 中一定有更好的方法来做到这一点,对吧?

4

9 回答 9

12

如果您有相同的异常处理代码IOExceptionFileNotFoundException那么您可以只用一个catch子句以更紧凑的方式重写您的示例:

try {
    InputStream input = new BufferedInputStream(new FileInputStream(file));
    try {
        // ...
        input.read(buffer);
        // ...
    }
    finally {
        input.close();
    }
}
catch (IOException e) {
    e.printStackTrace();
}

如果您可以传播异常,您甚至可以摆脱外部try-catch,这可能比手动打印堆栈跟踪更有意义。如果您没有在程序中捕获一些异常,您将自动为您打印堆栈跟踪。

此外,手动关闭流的需求将在 Java 7 中通过自动资源管理得到解决。

通过自动资源管理和异常传播,代码减少到以下内容:

try (InputStream input = new BufferedInputStream(new FileInputStream(file))) {
    // ...
    input.read(buffer);
    // ...
}
于 2011-06-06T09:54:41.233 回答
2

通常这些方法都包含在库中。除非您想在此级别编写,否则最好创建自己的辅助方法或使用现有的方法,如FileUtils

String fileAsString = Fileutils.readFileToString(filename);
// OR
for(String line: FileUtils.readLines(filename)) {
    // do something with each line.
}
于 2011-06-06T10:03:24.523 回答
1

有时您可以将代码简化为以下内容:

public void foo(String name) throws IOException {
    InputStream in = null;
    try {
        in = new FileInputStream(name);
        in.read();
        // whatever
    } finally {
        if(in != null) {
            in.close();
        }
    }
}

当然,这意味着调用者foo必须处理,IOException但无论如何大部分时间都应该是这种情况。最后,您并没有真正减少那么多复杂性,但是由于嵌套的异常处理程序更少,代码变得更具可读性。

于 2011-06-06T11:43:25.887 回答
1

我不知道这是否正确,但是您可以将所有代码放在同一个 try 块中,然后将不同的 catch 块紧接在一起。

try {
  ...
}
catch (SomeException e) {
  ...
}
catch (OtherException e) {
  ...
}
于 2011-06-06T09:51:17.920 回答
1

我在不使用实用程序的情况下对此的看法是:

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();
    }
}

不是单线,但也不是很糟糕。例如,使用 Apache Commons IO 将是:

//...
buffer = FileUtils.readFileToByteArray(file);
//...

需要记住的是,标准 Java 缺少许多每个人都需要的这些小实用程序和易于使用的接口,因此您必须在您的项目中依赖一些支持库,如Apache CommonsGoogle Guava等,(或实现您的自己的实用程序类)。

于 2011-06-06T13:21:28.310 回答
1

如果您想在纯 Java 中执行此操作,您发布的代码看起来还可以。

您可以使用 3rd 方库,例如 Commons IO,您需要在其中编写更少的代码。例如

在以下位置查看 Commons IO:

http://commons.apache.org/io/description.html

于 2011-06-06T09:54:19.403 回答
0

使用org.apache.commons.io.FileUtils.readFileToByteArray(File)该软件包中的或类似的东西。它仍然会抛出 IOException,但它会为您处理清理工作。

于 2011-06-06T09:54:59.997 回答
0

尝试以下操作:

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();
}
于 2011-06-06T09:57:00.150 回答
0

Google guava 试图通过引入Closeables来解决这个问题。

否则,您必须等到JDK 7 的AutoCloseable出现,因为它解决了抛出 IOException 的一些情况。

于 2011-06-06T10:00:36.473 回答