Java文件流“java.io.IOException: Stream closed”异常解决
初学者在Java的io流操作中往往最容易忘记的就是处理完之后流的关闭,但是好不容易记起来了,却又出现java.io.IOException: Stream closed的异常,现在以记事本案例来演示此问题。

该异常提示“流”已经关闭,但是我们观察源代码,发现我们打开了两个流,之后关闭这两个流,但为什么提示流已经关闭呢?

要想解决这一个问题,首先需要了解“修饰类”的概念,在这里“FileWriter 是被修饰者,BufferedWriter 是修饰者”,也可以通过增加File类缓冲提高学性能。
既然知道“FileWrite”是被修饰者,“BufferedWrite”是修饰者,如果用“嵌套”这个概念来理解这一问题,那么很明显,“FileWrite”是嵌套在“BufferedWrite”中的,所以,当先关闭“FileWrite”流时,“BufferedWrite”自然没有了修饰对象,所以会抛出异常。
解决方法就是先关闭“BufferedWrite”修饰流,再关闭“FillWrite”流即可,如下图:

问题成功解决!
另外多说一句,“FileReader”和“BufferedReader”没有此问题。
在最后附上源代码,仅供参考:
/*
* 引包
*/
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.awt.event.*;
/**
* 记事本界面设计
* @author guoqiang
*
*/
public class Window extends JFrame implements ActionListener {
/* 定义组件 */
JTextArea mainJTA = null; // 主界面的文本输入
JMenuBar jmenubar = null; // 菜单条
JMenu jmenu = null; // 一级菜单
JMenuItem jmenuitemOpen = null; // 菜单选项
JMenuItem jmenuitemSave = null; // 保存
/**
* 构造函数,实现组建的初始化
*/
public Window() {
/* 创建对象 */
mainJTA = new JTextArea();
jmenubar = new JMenuBar();
jmenu = new JMenu("文件 (Alt+F)");
jmenuitemOpen = new JMenuItem("打开");
jmenuitemSave = new JMenuItem("保存");
/* 设置助记符 */
jmenu.setMnemonic('F');
/* 设置页面布局 */
this.setLayout(new BorderLayout());
/* 添加组件 */
this.add(mainJTA);
/* 注册监听 */
jmenuitemOpen.addActionListener(this);
jmenuitemOpen.setActionCommand("open");
jmenuitemSave.addActionListener(this);
jmenuitemSave.setActionCommand("save");
// 添加菜单条
this.setJMenuBar(jmenubar);
jmenubar.add(jmenu);
jmenu.add(jmenuitemOpen);
jmenu.add(jmenuitemSave);
/* 设置窗体属性 */
this.setSize(500, 350);
this.setLocation(300, 200);
this.setTitle("记事本");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setIconImage(new ImageIcon("images/star.gif").getImage());
/* 显示窗体 */
this.setVisible(true);
}
/**
* 重写ActionListener的方法
*/
@Override
public void actionPerformed(ActionEvent e) {
// 判断哪个菜单被选中
if (e.getActionCommand().equals("open")) {
// 创建文件选择对象
JFileChooser jfilechooser = new JFileChooser();
jfilechooser.setDialogTitle("请选择文件..."); // 选择文件的对话框的标题
jfilechooser.showOpenDialog(null); // 按照默认属性弹出对话框, null表示默认属性
jfilechooser.setVisible(true); // 窗体可见
// 得到用户选择的文件路径
String fileName = jfilechooser.getSelectedFile().getAbsolutePath(); // 得到绝对路径
/* 文件流 */
FileReader filereader = null;
BufferedReader bufferedreader = null;
/* 异常处理 */
try {
/* 文件字符流 */
String s = null;
String allChar = null;
filereader = new FileReader(fileName); // 德大哦文件路径
bufferedreader = new BufferedReader(filereader);
while ((s = bufferedreader.readLine()) != null) {
allChar += s + "\r\n"; // 字符串拼接
}
/* 在JTextArea中显示 */
mainJTA.setText(allChar); // 该方法继承于javax.swing.text.JTextComponent
} catch (Exception e1) {
e1.printStackTrace();
} finally {
// 关闭文件流
try {
bufferedreader.close();
filereader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
} else if (jmenuitemSave.getActionCommand().equals("save")) { // 选择保存菜单
// 另存为对话框
JFileChooser jfilechooser = new JFileChooser();
jfilechooser.setDialogTitle("另存为...");
jfilechooser.showSaveDialog(null); // 按照默认属性弹出对话框, null表示默认属性
jfilechooser.setVisible(true);
/* 得到保存的路径 */
String savePath = jfilechooser.getSelectedFile().getAbsolutePath(); // 得到绝对路径
/* 此处应该判断是否真的选择了地址,如果只是打开却没有选择,会抛出 java.lang.NullPointerException*/
/* 写入到指定文件 */
FileWriter filewrite = null;
BufferedWriter bufferedwrite = null;
try {
filewrite = new FileWriter(savePath);
bufferedwrite = new BufferedWriter(filewrite);
// 将JTextArea中的内容写入到指定文件
bufferedwrite.write(this.mainJTA.getText());
} catch (Exception e2) {
e2.printStackTrace();
} finally {
try {
/* 关闭文件流 */
bufferedwrite.close();
filewrite.close();
} catch (Exception e3) {
// TODO: handle exception
e3.printStackTrace();
}
}
}
}
}