Java数组序列化追加存储与反序列化读取方案咨询
Java序列化对象追加到文件及读取所有对象的实现方案
一、问题分析
你的原代码存在两个核心问题:
- 使用
FileOutputStream时未开启追加模式,每次调用都会覆盖原有文件内容; - 直接用
ObjectOutputStream追加写入时,每次都会写入序列化头部,导致后续读取时抛出反序列化异常。
下面给出针对性的修改方案,实现数据追加和完整读取。
二、写入(追加)实现
1. 自定义可追加的对象输出流
需要自定义一个输出流,避免重复写入序列化头部:
import java.io.IOException; import java.io.ObjectOutputStream; import java.io.OutputStream; public class AppendableObjectOutputStream extends ObjectOutputStream { public AppendableObjectOutputStream(OutputStream out) throws IOException { super(out); } @Override protected void writeStreamHeader() throws IOException { // 追加模式下跳过序列化头部写入,仅保留第一次写入的头部 reset(); } }
2. 修改写入方法
开启文件追加模式,并根据文件是否已有内容选择对应的输出流:
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public static void order_history(String name, int keychain_count) { String[][] newArray = {{name, String.valueOf(keychain_count)}}; File tempFile = new File("t.tmp"); boolean fileHasContent = tempFile.exists() && tempFile.length() > 0; // 使用try-with-resources自动关闭流,避免资源泄漏 try (FileOutputStream fos = new FileOutputStream(tempFile, true); ObjectOutputStream oos = fileHasContent ? new AppendableObjectOutputStream(fos) : new ObjectOutputStream(fos)) { oos.writeObject(newArray); } catch (IOException e) { e.printStackTrace(); } }
三、读取所有对象实现
通过循环读取文件中的所有序列化对象,直到文件末尾:
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.List; public static List<String[][]> readAllOrderHistory() { List<String[][]> historyList = new ArrayList<>(); try (FileInputStream fis = new FileInputStream("t.tmp"); ObjectInputStream ois = new ObjectInputStream(fis)) { while (true) { try { // 读取单个序列化对象并转换为目标类型 String[][] item = (String[][]) ois.readObject(); historyList.add(item); } catch (ClassNotFoundException e) { e.printStackTrace(); break; } catch (IOException e) { // 捕获EOFException表示已读取到文件末尾 if (e instanceof java.io.EOFException) { break; } else { e.printStackTrace(); break; } } } } catch (IOException e) { e.printStackTrace(); } return historyList; }
四、注意事项
String[][]本身是可序列化的(数组和String均实现了Serializable接口),无需额外处理;- 可以替换临时文件路径为系统临时目录(
System.getProperty("java.io.tmpdir")),提升代码兼容性; - 异常处理可根据业务需求调整,比如抛出自定义异常而非仅打印堆栈。
内容的提问来源于stack exchange,提问作者VS Puzzler
相关产品推荐
相关产品推荐

