You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将文本文件读取为对象数组?读写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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:07:38