关于java:如何在使用缓冲读取器读取文件时处理异常?

How to handle exceptions when reading files with buffered reader?

我已经编写了从文本文件中读取文本(JSON,XML等)的代码,并将其转换成字符串,然后由其他代码将其转换成普通的Java对象或由杰克逊注释的POJOS。

我不确定我的代码是否正确地处理了异常。到目前为止,我已经使用了我的代码后提到的原则(请阅读下面的选民!!!!),开发代码。注意,我不能使用REST资源,因为我被Java 6(即使我的项目JRE是1.8)所困扰。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.testing;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class JunkEx {

    public static void main(String[] args) {
        String filePath =".\\src\\test\
esources\\text-files\\orders\\orders-2017.txt"
;
        String contents = fileToString(filePath);
        System.out.println(contents);
    }

    private static String fileToString(String filePath) {
        StringBuilder stringBuilder = null;
        BufferedReader br = null;

        try {
        br = new BufferedReader(new FileReader(filePath));
        stringBuilder = new StringBuilder();
        String currentLine;
        while ((currentLine = br.readLine()) != null) {
            stringBuilder.append(currentLine);
            stringBuilder.append("
"
);
        }

        }catch (FileNotFoundException ex1) {
            ex1.printStackTrace();
        }catch (IOException ex2) {
            ex2.printStackTrace();
        }finally {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return stringBuilder.toString();
    }

}

原则:

1)首先捕获最具体的异常,然后在异常层次结构中捕获它上面的异常。即catch filenotfoundexception first和ioexception later。此处参考第5点

2)不要从finally块内部返回,因为finally总是在完全或突然尝试"完成"时执行。请参考此答案。

3)清除finally块中的缓冲读卡器等资源。请参阅此处的第1点。

4)不要让"危险"方法的调用方(即可能引发异常的调用方)知道/抛出其中的每个异常。即危险方法不应"throws fileNotFoundException、ioException…等"。参考此链接,特别是最后一段

代码缺陷:如果前两个catch块中的任何一个被执行,那么很可能整个文件没有被读取。但是,无论如何,我的方法将返回一个字符串。字符串可能为空或不完整。

问题-

1)当文本文件未成功转换为字符串时,我想引发异常,即执行三个catch块中的一个。我应该将异常包装在一个通用异常对象内的每个catch块中,然后抛出该异常还是执行其他操作?

2)如何改进/修复此代码的异常处理?

项目结构:enter image description here


简单的回答:完全不要捕获异常。让呼叫者接住他们。他是需要知道的人,知道如何处理他们。这种方法当然不会。

4) Do not make the callers of the"dangerous" method (i.e. which could throw exceptions), have to know/throw each of the exceptions inside it. I.e dangerous method should not"throws FileNotFoundException, IOException...etc". refer this link, specifically the last paragraph.

我不太重视这个"原则",无论如何,它在这里实际上并不适用。唯一抛出的异常是IOExceptionFileNotFoundException,它是从它派生的。如果打电话的人不愿意,他不必同时处理这两件事。但是,如果缺少的文件构成部署错误,那么他可能希望这样做。


您有两种选择:

  • 不要捕获异常并让调用者处理它们
  • 捕获异常并抛出您自己的自定义异常,比如FileToStringFailedException,它包装了实际的异常。包装部分非常重要,因此当调用链上的某个人执行printStackTrace()时,您会得到一个解释实际失败的Caused By部分。
  • 两个选项都有效,您选择哪一个取决于总体设计。对于一些简单的事情,我只会让异常向上渗透;如果我正在设计一个包含其他自定义包装异常的大型复杂库,我可能会选择选项2。

    如果没有更多的上下文来说明你在做什么,以及它在哪里适合你的系统,就不可能说一个选项是"更好的"。

    无论你做什么,都不要干涉实际的例外。例外是程序员,而不是用户。如果您希望用户出现"友好"错误,请在异常显示给用户时执行该操作,但请确保为程序员记录原始异常。否则,当您的"友好"异常隐藏了解决问题所需的关键信息时,您会非常后悔。