简体   繁体   English

Java List.stream.forEach Lambda表达式内部未处理的IOException

[英]Unhandled IOException Inside Java List.stream.forEach Lambda Expression

I am using the Stream API introduced in Java 8 to run a method for each string in a list. 我正在使用Java 8中引入的Stream API来为列表中的每个字符串运行一个方法。

public boolean initFile() throws IOException
{
    if (this.outFile.exists()) {
        this.outFile.delete();
    }
    return this.outFile.createNewFile();
}

public void writeStringToFile(String str, boolean addNewLine) throws IOException
{
    if (this.mode != FileMode.READ) {
        if (this.initFile()) {
            FileWriter fileWriter;
            if (this.mode == FileMode.APPEND)
                fileWriter = new FileWriter(outFile.getAbsolutePath(), true);
            else
                fileWriter = new FileWriter(outFile.getAbsolutePath());
            fileWriter.write(str);
            if (addNewLine)
                fileWriter.write("\n");
            fileWriter.close();
        } else {
            throw new IOException("IO Error: The file could not be initialized.");
        }
    } else {
        throw new IOException("Cannot write to a file with the mode FileMode.READ");
    }
}

public void writeListToFile(List<String> strings, boolean addNewLine) throws IOException
{
    strings.stream().forEach(s -> this.writeStringToFile(s, addNewLine)); // Unhandled IOException from writeStringToFile
}

As you can see, the method signature states to throw all IOExceptions and the writeToString method inside the stream has the potential to throw an IOException. 如您所见,方法签名指出要抛出所有IOException,而流中的writeToString方法有可能抛出IOException。 However, the Java compiler is giving me an error stating that there is an unhandled IOException on the stream line. 但是,Java编译器给我一个错误,指出在流线上存在未处理的IOException。

Why would the exception inside the stream not get thrown like any other exception inside the method? 为什么流中的异常不会像方法中的其他任何异常一样抛出? Is there any way that I can remedy this without putting a try-catch statement in the forEach lambda expression? 没有任何方法可以在不将try-catch语句放入forEach lambda表达式中的情况下进行纠正?

Don't reinvent the wheel. 不要重新发明轮子。 Use the features offered by the Java API. 使用Java API提供的功能。

public void writeListToFile(List<String> strings, boolean addNewLine) throws IOException
{
  if(this.mode == FileMode.READ)
      throw new IOException("Cannot write to a file with the mode FileMode.READ");

  Files.write(outFile.toPath(), addNewLine? strings:
      Collections.singleton(strings.stream().collect(Collectors.joining())),
    this.mode==FileMode.APPEND? StandardOpenOption.APPEND: StandardOpenOption.CREATE);
}

Files.write will write all lines of an Iterable (which includes Collection s) and that's it. Files.write将写入Iterable所有行(包括Collection ),仅此而已。 Your obstacle of supporting the addNewLine option can be solved by collecting all String s into one in the case, addNewLine is false , hence, there will be no line-feeds between them then. 支持addNewLine选项的障碍可以通过在所有情况下将所有String集合为一个来解决, addNewLinefalse ,因此它们之间将没有换行。 Otherwise, Files.write will append line-feeds to every string. 否则, Files.write会将Files.write附加到每个字符串。

There is no point in manually dealing with testing for the existence of files or trying to delete or create them. 手动处理文件是否存在或尝试删除或创建它们毫无意义。 Regardless of whether you create your own Writer or use Files.write , these implementations will already report failures regarding existence/non-existence or failed attempts of creating the target file via IOException s, so you don't need to do it yourself. 无论您是创建自己的Writer还是使用Files.write ,这些实现都将报告有关存在/不存在的失败或通过IOException创建目标文件的尝试失败,因此您无需自己进行操作。

Even worse, whatever File.exists() , File.delete() , or File.createNewFile() may return, is already an outdated information upon your subsequent I/O operation, eg creating/using a Writer , and does not guaranty anything about whether the subsequent operation will succeed or fail. 更糟糕的是,无论File.exists()File.delete()File.createNewFile()可能返回什么,已经是您后续I / O操作(例如创建/使用Writer File.createNewFile()的过时信息,并且不保证任何事情。有关后续操作是成功还是失败的信息。

you have to use try catch in you writeListToFile method like this: 您必须使用try catch在您的writeListToFile方法中,如下所示:

  public void writeListToFile(List<String> strings, boolean addNewLine) throws Exception {
    strings.stream().forEach(s -> {
        try {
            writeStringToFile(s, addNewLine);
        } catch (IOException ex) {
            //you can Log it immediately or throw ex;
            Logger.getLogger(C.class.getName()).log(Level.SEVERE, null, ex);
        }
    });
    // Unhandled IOException from writeStringToFile
}

why? 为什么? look at this point s -> {}.Here {} means that compiler make new Interface (Consumer) 看这点s-> {}。这里{}表示编译器创建了新的Interface(Consumer)

 void forEach(Consumer<? super T> action);

and new Class implements this interface and pass s parameter to it's accept method.Can you throw Exception of new Class in your method? 新类实现此接口并将s参数传递给它的accept方法。您可以在方法中抛出新类的异常吗? No.So you have to try catch of every item of foreach 不,所以您必须尝试捕获foreach的每个项目

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

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