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

Java中将多值文件加载至ArrayList时出现StreamCorruptedException问题求助

解决java.io.StreamCorruptedException: invalid stream header错误

嘿,这个错误的根源很清晰——你用错了文件读取工具!

你现在的文件是普通的文本格式,每行都是accountNumber=xxx这样的键值对,但你却用了ObjectInputStream来读取它。这个类是专门用来读取Java序列化后的二进制对象的,它一开头就会去寻找序列化对象特有的二进制头部,结果读到的却是文本的"acco"(错误里的6163636F就是"acco"的ASCII码),自然就抛出了流头部无效的错误。

下面分两种情况给你解决方案:


情况1:你就是想读取这个文本格式的文件

那你需要用读取文本的工具类,比如BufferedReader,逐行读取后解析内容到Account对象里。这里给你写个完整的示例:

// 先确保你的Account类有对应的getter/setter方法
private static ArrayList<Account> accounts = new ArrayList<>(); // 全局静态变量

private static void loadAccounts() throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader("AccountFile"))) {
        String line;
        // 逐行读取文件内容
        while ((line = br.readLine()) != null) {
            Account account = new Account();
            // 按逗号分割每个键值对,同时忽略逗号后的空格
            String[] keyValuePairs = line.split(",\\s*");
            
            for (String pair : keyValuePairs) {
                // 分割键和值
                String[] parts = pair.split("=");
                String key = parts[0].trim();
                String value = parts[1].trim();
                
                // 根据键设置Account的属性,注意去掉branchName的单引号
                switch (key) {
                    case "accountNumber":
                        account.setAccountNumber(Integer.parseInt(value));
                        break;
                    case "branchName":
                        account.setBranchName(value.replace("'", ""));
                        break;
                    case "balance":
                        account.setBalance(Integer.parseInt(value));
                        break;
                    case "customerNumber":
                        account.setCustomerNumber(Integer.parseInt(value));
                        break;
                }
            }
            accounts.add(account);
        }
    }
}

这段代码会逐行解析你的文本文件,把每一行的内容封装成Account对象,再加入到ArrayList里。


情况2:你原本想使用Java序列化(存储对象而非文本)

如果你的初衷是把ArrayList<Account>序列化到文件里,那你之前的写入步骤完全错误——你手动写了文本,而不是用ObjectOutputStream来序列化对象。

首先,你的Account类必须实现Serializable接口(否则无法被序列化):

import java.io.Serializable;

public class Account implements Serializable {
    // 类的属性
    private int accountNumber;
    private String branchName;
    private int balance;
    private int customerNumber;
    
    // 构造方法、getter和setter方法
    public Account() {}
    
    public void setAccountNumber(int accountNumber) {
        this.accountNumber = accountNumber;
    }
    // 其他getter/setter同理...
}

然后,正确的序列化写入方法应该是这样的:

private static void saveAccounts(ArrayList<Account> accounts) throws IOException {
    // 使用try-with-resources自动关闭流
    try (FileOutputStream fos = new FileOutputStream("AccountFile");
         ObjectOutputStream oos = new ObjectOutputStream(fos)) {
        oos.writeObject(accounts);
    }
}

最后,修正你原来的loadAccounts方法(注意:方法内部不能定义静态变量,把accounts改成全局静态变量):

private static ArrayList<Account> accounts = new ArrayList<>();

private static void loadAccounts() throws IOException, ClassNotFoundException {
    try (FileInputStream fileInputStream = new FileInputStream("AccountFile");
         ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
        accounts = (ArrayList<Account>) objectInputStream.readObject();
    }
}

这样修改后,当你先调用saveAccounts把对象序列化到文件,再调用loadAccounts读取,就不会报错了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 05:02:44