【问题标题】:FileWriter issue - unreported IOEXception which must be caughtFileWriter 问题 - 必须捕获的未报告的 IOEXception
【发布时间】:2015-12-30 03:32:20
【问题描述】:

我在 Java 中尝试使用 FileWriter 写入文件时遇到了问题。简单地声明 FileWriter writer = new FileWriter("filelocation"); 会产生一个必须捕获的未报告的 IOException。

为了纠正这个问题,我自然地将我的 FileWriter 放在 try-catch 块中,但这会导致范围问题。为了解决这个问题,我尝试在 try catch 块之前声明 FileWriter 并在 try catch 中分配位置。当我想使用 FileWriter 时,在 try catch 块之后,它告诉我它可能尚未初始化。我不确定如何处理这个问题,并且在 Java 1.7 或类似版本中从未遇到过这个问题。

这是我最后情况的一个例子,以防我不清楚;

Scanner userInput = new Scanner(System.in);
FileWriter writer;
try {
    System.out.println("Enter the file directory you would like to store in");
    String fileLocation = userInput.nextLine();
    writer = new FileWriter(fileLocation);
} catch(java.io.IOException e) {
    System.out.println("Error message");
}
writer.write("Stuff"); //writer may not have been initialized

【问题讨论】:

  • 这是预期行为。你需要在构造函数调用下的try块中执行writer.write
  • 问题在于我的实际代码中,在我使用编写器之前还有大约 90 行代码。我认为将所有内容都放在 try 块中是不好的做法。我在这方面错了吗?顺便说一句,这似乎是一种奇怪的预期行为。如果在 try catch 中初始化 FileWriter 时出错,它会在抛出错误时退出该方法,因此永远不会调用 writer.write。我对 1.8 的看法完全不同了!
  • Jason:它在 try 块中在语义上是正确的。但是,更合适的是try-with-resources
  • 好的,我来看看。我应该能够按照您告诉我的内容对其进行排序,非常感谢您!
  • Java FileWriter 自 1997 年以来已抛出 IOExceptions。这不是“Java 1.8 的问题”。

标签: java exception java-io filewriter


【解决方案1】:

好方法:

System.console().printf("Enter the file directory you would like to store in");
String location = System.console().readLine();
try (FileWriter writer = new FileWriter (location)) {
  writer.write("Stuff");
} catch (IOException e) {
  new RuntimeException("Error message", e).printStackTrace();
}

解释:

  1. System.console().printf() 允许在 stdout 上打印消息。 System.out 可能是首选,因为“控制台”不是严格要求的。
  2. 使用System.console() 进行控制台管理。更容易和更清晰。不要忘记分配控制台(即不要使用javaw 可执行文件)。
  3. 使用try-with-resources statement打开流
  4. printStackTrace() 打印在 stderrcall stack 上,可以轻松在代码中查找错误位置。
  5. 我已经构建了一个新的异常来附加您的错误消息和堆栈跟踪添加堆栈中的“catch”位置。

建议:

  1. 使用字节流进行文件访问(即FileOutputStream)。它可以强制执行字符集(即OutputStreamWriter)和缓冲(即BufferedOutputStreamBufferedWriter)。
  2. 使用字节流也可以切换到NIO Channel API
  3. 使用StandardCharsets 访问默认(并且大部分是常用的)字符集(所有 JVM 实现必须支持的字符集)
  4. 阅读The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
  5. 调用printStackTrace() 不是很好,您应该快速引入日志系统来打印消息。
  6. 如果是CLI,请在使用日志系统时注意不要让用户混淆系统交互(即提示用户输入)和反馈(即进度消息)

【讨论】:

  • 由于 OP 显然不关心编码,所以使用FileWriter 是更好的选择。现在不要因为您可能永远不需要的东西而使代码复杂化。如果需要发生变化,您可以随时重构。 --- 捕获异常并打印堆栈跟踪,然后让代码继续运行,这是灾难的根源。除非您已处理异常,否则您很少希望执行以下代码。
  • 为什么您认为使用System.console()System.out 打印消息更好?尤其是当您不那样打印堆栈跟踪时?
  • 为什么要创建一个新的RuntimeException(创建一个全新但无用的堆栈跟踪),只是为了打印抛出的IOException 的堆栈跟踪?
  • 您应该意识到System.console() 可以返回null,具体取决于所使用的IDE。坚持使用System.out打印到控制台,避免使用易异常代码的风险。
  • @Andreas 我看到太多缺乏编码/字符集管理,不能教育傻瓜(不是借口)。参考The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
【解决方案2】:

你说“自然地”你把它放在一个 try-catch 块中。这并不自然,因为有两种处理方式,另一种方式更常见:

  • 在 try-catch 块中处理异常。
  • 不处理异常,但声明您的方法抛出异常,并允许它向上级联调用堆栈。

您的代码看起来像是在 main 方法中,因此您可以添加 throws IOException

public static void main(String[] args) throws IOException {

但是,在您的特定情况下,您是从用户提示中获取文件位置的,因此与其让程序因错误而死掉,不如告诉用户该错误并提示您输入新的名字。

另外,记得关闭你的资源。

public static void main(String[] args) throws IOException {
    Scanner userInput = new Scanner(System.in);
    FileWriter writer;
    do {
        System.out.println("Enter the file name you would like to store in");
        String fileLocation = userInput.nextLine();
        if (fileLocation.trim().isEmpty())
            return; // Exit program when user pressed enter with a name
        try {
            writer = new FileWriter(fileLocation);
        } catch(java.io.IOException e) {
            System.out.println("Cannot write to file: " + e);
            writer = null;
        }
    } while (writer == null);
    try {
        writer.write("Stuff"); //writer may not have been initialized
    } finally {
        writer.close();
    }
}

writeclose 在技术上仍然可以抛出错误(例如磁盘已满),我们允许级联并终止程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    • 1970-01-01
    相关资源
    最近更新 更多