使用Stream API与Lambda创建FileOutputStream时出错,求解决方法
问题:使用Stream API操作FileOutputStream时写入第二个元素触发异常
我用FileOutputStream创建文件,用普通for循环可以正常执行:
public class EjemploFileOutputStream { /** * @param args */ public static void main(String[] args) { OutputStream fOut = null; try { fOut = new FileOutputStream("primero.dat"); for(int i = 0; i < 1000; i++) { fOut.write(i); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fOut != null) try { fOut.close(); } catch (IOException e) { e.printStackTrace(); } } } }
但改用Stream API和Lambda表达式时出现错误,代码如下:
public class EjemploFileOutputStream { static OutputStream fOut2 = null; /** * @param args * @throws FileNotFoundException */ public static void main(String[] args) throws FileNotFoundException { List<Number> cantidades = Arrays.asList(10, 20, 30, 40, 50); try { fOut2 = new FileOutputStream("primero3.dat"); } catch (FileNotFoundException e1) { e1.printStackTrace(); } cantidades.stream().map(cantidad->cantidad.intValue()).forEach(cantidad -> { try { fOut2.write(cantidad); } catch (IOException e1) { e1.printStackTrace(); } finally { if (fOut2 != null) try { fOut2.close(); } catch (IOException e) { e.printStackTrace(); } } }); } }
错误现象
- 列表第一个值(10)能正常写入文件
- 处理第二个值(20)时触发
IOException,提示流已经关闭
问题原因
你在forEach的Lambda表达式里,把关闭流的逻辑写在了finally块中——这意味着每处理一个元素就会关闭一次流。第一个元素写完后流已经被关闭,第二个元素再调用write时,自然会触发流已关闭的异常。
解决方法
把关闭流的逻辑移到forEach外面,和普通for循环的写法保持一致,只在所有元素写完后关闭一次流:
修正后的代码
public class EjemploFileOutputStream { /** * @param args */ public static void main(String[] args) { OutputStream fOut2 = null; List<Number> cantidades = Arrays.asList(10, 20, 30, 40, 50); try { fOut2 = new FileOutputStream("primero3.dat"); cantidades.stream() .map(Number::intValue) .forEach(cantidad -> { try { fOut2.write(cantidad); } catch (IOException e) { e.printStackTrace(); } }); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (fOut2 != null) { try { fOut2.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
更优写法:使用try-with-resources(自动关流)
Java 7及以上推荐用try-with-resources语法,它会自动在代码块结束后关闭流,无需手动写finally,更简洁安全:
public class EjemploFileOutputStream { /** * @param args */ public static void main(String[] args) { List<Number> cantidades = Arrays.asList(10, 20, 30, 40, 50); try (OutputStream fOut2 = new FileOutputStream("primero3.dat")) { cantidades.stream() .map(Number::intValue) .forEach(cantidad -> { try { fOut2.write(cantidad); } catch (IOException e) { e.printStackTrace(); } }); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
内容的提问来源于stack exchange,提问作者Angel Picallo
相关产品推荐
相关产品推荐

