如何将文本文件读取为对象数组?读写House对象遇流异常
问题分析与解决方案
你遇到的核心问题是读取和写入的方式完全不匹配,再加上序列化相关的两个关键错误,导致了当前的异常和读取失败。咱们一步步拆解解决:
1. 核心矛盾:写入是文本,读取却用对象序列化
你用FileWriter把House对象的toString()文本写入了output.txt,但读取时却用ObjectInputStream来反序列化二进制对象流——这就像把苹果放进纸盒子,却想用开罐头的工具打开,肯定会报StreamCorruptedException(错误里的invalid stream header: 3134313B其实是文本字符的ASCII码,说明文件里是纯文本而非序列化的二进制数据)。
2. 必须解决的序列化前提:House类要实现Serializable接口
要让对象能被序列化/反序列化,House类必须实现java.io.Serializable标记接口,否则即使使用正确的流也会失败。
3. 修正读取的无限循环逻辑
ObjectInputStream.readObject()不会在流末尾返回null,而是会抛出EOFException,原来的while(cont)逻辑会一直循环直到抛出异常,这也是你之前无限循环的根源。
修改后的完整代码
第一步:更新House类,实现Serializable接口
import java.io.Serializable; public class House implements Serializable { // 新增Serializable标记接口 String address; double area; boolean garage; public House(String address, double area, boolean garage){ this.address=address; this.area = area; this.garage = garage; } // 原有的getter/setter保留 public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public double getArea() { return area; } public void setArea(double area) { this.area = area; } public boolean isGarage() { return garage; } public void setGarage(boolean garage) { this.garage = garage; } @Override public String toString() { return address + ";" + area + ";" + garage; } }
第二步:修正写入代码,用ObjectOutputStream序列化对象
try { // 替换FileWriter为ObjectOutputStream,底层用FileOutputStream处理二进制 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("output.txt")); for(House house : listH) { oos.writeObject(house); // 直接写入对象,而非toString文本 } oos.close(); System.out.println("Successful writing"); } catch (IOException e) { e.printStackTrace(); System.out.println("Couldn't write"); }
第三步:修正读取代码,处理EOFException终止循环
try { List<House> listH = new ArrayList<>(); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("output.txt")); // 循环读取直到抛出EOFException(流读取完毕) while(true) { try { House house = (House) ois.readObject(); listH.add(house); } catch (EOFException e) { break; // 流读取完毕,终止循环 } } ois.close(); mainmenu(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }
额外说明:如果想存储为可读文本
如果你其实想把对象以CSV风格的可读文本存储(比如address;area;garage),那读取时就不能用ObjectInputStream,而是用BufferedReader逐行读取,手动拆分数据并构建House对象。这种情况下写入用FileWriter是没问题的,读取逻辑调整如下:
try { List<House> listH = new ArrayList<>(); BufferedReader reader = new BufferedReader(new FileReader("output.txt")); String line; while((line = reader.readLine()) != null) { String[] parts = line.split(";"); String address = parts[0]; double area = Double.parseDouble(parts[1]); boolean garage = Boolean.parseBoolean(parts[2]); listH.add(new House(address, area, garage)); } reader.close(); mainmenu(); } catch (IOException e) { e.printStackTrace(); }
这种方式不需要House实现Serializable接口,适合需要人类可读的文本存储场景。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

