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

ArrayList序列化与反序列化问题:读取文件返回空集合

解决Java序列化ArrayList后反序列化获取空集合的问题

问题描述

尝试将ArrayList<User>写入文件,读取后输出完整集合时得到空结果,后续计划从中随机选取元素。以下是原代码:

原序列化代码

public void oStream(User user) {
    ArrayList<User> people = new ArrayList<User>();
    people.add(user);
    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt", true))) {
        oos.writeObject(people);
    } catch (IOException ex) {
        System.out.println(ex.getMessage());
    }
}

原反序列化代码

public ArrayList<User> iStream() {
    ArrayList<User> people = new ArrayList<>();
    try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"))) {
         for (User p : people)
              people.add(p);
         people = (ArrayList<User>) ois.readObject();
    } catch (IOException | ClassNotFoundException e) {
          throw new RuntimeException(e);
    }
    return people;
}

User类代码

public class User implements Serializable {
    private String login;
    private String password;
    private String email;
    private String date;

    public User(String login, String password, String email, String date) {
        this.login = login;
        this.password = password;
        this.email = email;
        this.date = date;
    }

    public User(String login, String password, String email) {
        this.login = login;
        this.password = password;
        this.email = email;
    }

    public User() {}

    // getter和setter方法省略
}

错误原因分析

  1. 序列化使用追加模式:ObjectOutputStream初始化时会写入序列化头部信息,用追加模式(FileOutputStream第二个参数为true)会导致文件中存在多个头部,反序列化时无法正确解析后续对象,甚至只能读取第一个写入的集合(若多次调用oStream)。
  2. 反序列化中的无效循环:for (User p : people) people.add(p); 这段代码遍历的是初始为空的people集合,完全不会执行,属于冗余代码。
  3. 未处理文件初始化场景:第一次写入时文件不存在,读取会抛出异常,但原代码直接抛出运行时异常,导致无法正常创建初始集合。
  4. User类无toString方法:即使读取成功,输出集合时会打印对象哈希码,无法直观看到内容,容易误以为是空集合。

修正后的代码

修正后的序列化方法(支持添加新用户到现有集合)

public void oStream(User user) {
    ArrayList<User> people = new ArrayList<>();
    // 先读取文件中已有的集合
    try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"))) {
        people = (ArrayList<User>) ois.readObject();
    } catch (IOException | ClassNotFoundException e) {
        // 文件不存在或读取失败,说明是第一次写入,保持集合为空
    }
    // 添加新用户
    people.add(user);
    // 覆盖写入文件(避免多个序列化头部)
    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt"))) {
        oos.writeObject(people);
    } catch (IOException ex) {
        System.out.println(ex.getMessage());
    }
}

修正后的反序列化方法

public ArrayList<User> iStream() {
    ArrayList<User> people = new ArrayList<>();
    try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"))) {
        people = (ArrayList<User>) ois.readObject();
    } catch (EOFException e) {
        // 文件为空,返回空集合
    } catch (IOException | ClassNotFoundException e) {
        throw new RuntimeException(e);
    }
    return people;
}

给User类添加toString方法(方便查看集合内容)

在User类中添加:

@Override
public String toString() {
    return "User{" +
            "login='" + login + '\'' +
            ", password='" + password + '\'' +
            ", email='" + email + '\'' +
            ", date='" + date + '\'' +
            '}';
}

使用说明

  1. 调用oStream(User)添加用户时,会先读取文件中已有的集合,添加新用户后覆盖写入,确保文件中只有一个完整的集合。
  2. 调用iStream()会返回文件中存储的完整ArrayList<User>,可以直接输出或从中随机选取元素。

内容的提问来源于stack exchange,提问作者AlexSmith

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 01:57:44