Java序列化实现员工信息归档与读取系统的问题求助
问题分析与解决方案
1. 序列化失败的核心原因
你现在序列化CPersonAccount时出错,根源是类里的BufferedReader buf成员变量不可序列化。IO流对象(比如BufferedReader)不属于可序列化类型,而实现Serializable接口要求所有非transient的成员都必须支持序列化。
解决办法:
- 把
buf标记为transient,让序列化时跳过它:transient BufferedReader buf = new BufferedReader(new InputStreamReader(System.in)); - 更合理的方案:不要将
BufferedReader作为类的成员变量,而是在需要读取输入的方法内部临时创建,从根源避免序列化冲突。
2. 简化归档逻辑
你原来逐个写入属性的方式过于繁琐,修改后新建CPersonAccount对象序列化也不合理——应该直接序列化存储员工信息的CPersonData对象(前提是CPersonData也要实现Serializable)。
优化后的归档代码:
case 'S': // 注意路径反斜杠要转义为\\,否则会被当成转义字符 try (FileOutputStream fo = new FileOutputStream("C:\\myJava\\exercise\\ch12\\file\\ex6.tmp"); ObjectOutputStream os = new ObjectOutputStream(fo)) { // 直接序列化personArr中的CPersonData实体 for (int i = 0; i < obj.dataNum(); i++) { os.writeObject(obj.personArr[i]); // 若personArr是私有成员,需提供get方法 } } catch (IOException e) { e.printStackTrace(); }
3. 将归档逻辑封装到类中的异常处理
如果要把ObjectOutputStream的逻辑封装进CPersonAccount类,必须显式处理IOException——要么在方法上声明抛出,要么在方法内部捕获:
示例封装方法:
class CPersonAccount implements Serializable { CPersonData personArr[] = new CPersonData[1]; transient BufferedReader buf; // 标记为transient跳过序列化 // 封装归档方法 public void saveToFile(String filePath) throws IOException { try (FileOutputStream fo = new FileOutputStream(filePath); ObjectOutputStream os = new ObjectOutputStream(fo)) { for (int i = 0; i < dataNum(); i++) { os.writeObject(personArr[i]); } } } // 其他方法... }
调用时:
case 'S': try { obj.saveToFile("C:\\myJava\\exercise\\ch12\\file\\ex6.tmp"); } catch (IOException e) { e.printStackTrace(); }
4. 读取归档文件导入数组的实现
用ObjectInputStream循环读取对象,直到触发EOFException(表示文件读取完毕),再将读取到的CPersonData对象存入数组(或更灵活的ArrayList):
示例代码:
case 'L': // 假设L是读取归档的触发指令 List<CPersonData> tempList = new ArrayList<>(); try (FileInputStream fi = new FileInputStream("C:\\myJava\\exercise\\ch12\\file\\ex6.tmp"); ObjectInputStream is = new ObjectInputStream(fi)) { while (true) { try { CPersonData person = (CPersonData) is.readObject(); tempList.add(person); } catch (EOFException e) { break; // 读到文件末尾,退出循环 } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 将List转换为数组赋值给personArr obj.personArr = tempList.toArray(new CPersonData[tempList.size()]); } catch (IOException e) { e.printStackTrace(); }
注意:CPersonData必须实现Serializable,否则读取时会抛出序列化相关异常
额外建议
- 优先使用
try-with-resources语法,它会自动关闭流,避免手动关闭时的遗漏或异常。 - 用
ArrayList代替固定长度数组,更方便动态管理员工信息,序列化逻辑也会更简洁。
内容的提问来源于stack exchange,提问作者user23381600
相关产品推荐
相关产品推荐

