2016-12-25 88 views
-2

我想用一个很好的toString方法向一个文件逐行写一个自定义对象流。我到目前为止是这样的:写对象到文件流

private static void writeToFile(Set<Article> articles, Charset cs, Path path) throws IOException { 

    try(Writer w = 
      new BufferedWriter(
      new OutputStreamWriter(
      new FileOutputStream(path.toFile()), cs))) { 

     articles.stream().map(Article::toString).forEach(w::write); 

    } catch(IOException e) {} 

我收到错误未处理IOException异常在w上写::,因为我赶上这种异常是很奇怪吗?

其他点,是否可以逐行写入这些对象?

+0

的可能的复制[Java的8:我如何与例外扔在流方法的工作(http://stackoverflow.com/questions/23548589/java-8如何在异常情况下投掷方法在流中) – Natecat

+0

甚至没有类似 – zwiebl

+0

它们实际上非常接近,但相似性是隐藏的。 – HTNW

回答

2

foreach预计Consumer<? super E>,其中EStream的元素的类型。 Consumer<T>::accept的签名是

void accept(T t) 

注意它如何不抛出任何检查的异常。

现在,Writer::write确实抛出checked IOException,所以当你.foreach(w::write),编译器会抱怨,因为你要使用抛出异常(Writer::write)的方法,作为一个不(Consumer<T>::accept)。为了解决这个问题,你必须处理的foreach本身例外:

articles.stream().map(Article::toString).forEach(str -> { 
    try { 
     w.write(str + System.lineSeparator()); // Add a newline to each string. 
    } catch(IOException e) { 
     ... 
    } 
}); 

注意,而不是从上述流写入,可以构建整个String在内存中,然后将其所有的写一次。

String data = articles.stream().map(Article::toString).map(str -> str + System.lineSeparator()).reduce("", (acc, str) -> str + acc) 
w.write(data.substring(0, data.length()-1)); // Drop last newline 
3

PrintWriter是这样的情况下非常有用,因为它的方法不乱扔IOException。它也有print(Object)重载,它通过其toString方法将对象转换为字符串。 (实际上它调用String.valueOf其委托给toString前处理空值。)

不幸PrintWriter是一个有点老式API,因为它需要一个File而不是Path和字符集的名称,而不是实际的Charset的对象。但转换并不太大。

由于不需要中间调用map将对象转换为字符串,因此直接在集合上调用forEach即可。

下面是生成的代码:

static void writeToFile(Set<Article> articles, Charset cs, Path path) throws IOException { 
    try (PrintWriter pw = new PrintWriter(path.toFile(), cs.name())) { 
     articles.forEach(pw::println); 
    } 
}