java.io.StreamCorruptedException异常:二进制文件读取流头无效
序列化写入/读取二进制文件时抛出
StreamCorruptedException异常 我开发了一款从在线街道地图XML文件读取数据的应用,会把单个XML元素解析为存储数据的HashMap。但在尝试将解析后的数据写入二进制分块文件,再通过getAllTagBoundsFromBinaryFile()方法读取时,抛出了java.io.StreamCorruptedException: invalid stream header: 7372000F异常。
我的Tag抽象类继承自HashMap,每个XML元素都会解析为该类的实例,所以写入二进制文件的对象理论上都实现了Serializable接口:
public abstract class Tag<E extends Enum<E>> extends HashMap<E, Object>
负责创建二进制分块文件并写入TagBound(继承自Tag)对象的代码如下:
public class XMLWriter { private String directoryPath = "src/main/resources/chunks/"; // 用于处理/存储.bin文件路径及其对应TagBound的静态类ChunkFiles private static ChunkFiles chunkFiles = new ChunkFiles(); private static int chunkId = 0; public XMLWriter(TagBound bounds) { initChunkFiles(bounds); } public void initChunkFiles(TagBound bounds) { // 将边界分割为更小的块 for (TagBound parentChunk : Chunk.getQuadrants(bounds).values()) { Chunk childChunk = new Chunk(parentChunk); for (int j = 0; j < 4; j++) { // 获取块中的四个象限之一 TagBound child = childChunk.getQuadrant(j); // 将TagBound与对应的块文件路径加入HashMap:HashMap<TagBound, String> chunkFiles.appendChunkFile(child, directoryPath + "chunk_" + chunkId + ".bin"); // 创建块文件 createBinaryChunkFile(directoryPath + "chunk_" + chunkId + ".bin", child); chunkId++; } } } private static void createBinaryChunkFile(String path, TagBound bound){ try{ File file = new File(path); if (!file.exists()){ file.createNewFile(); } ObjectOutputStream oos = new AppendableObjectOutputStream(new FileOutputStream (path, true)); oos.writeObject(bound); oos.flush(); oos.close(); }catch (Exception e){ e.printStackTrace(); } } private static class AppendableObjectOutputStream extends ObjectOutputStream implements Serializable { public AppendableObjectOutputStream(OutputStream out) throws IOException { super(out); } @Override protected void writeStreamHeader() throws IOException {} } ...
读取二进制文件中TagBound对象的代码:
public static List<TagBound> getAllTagBoundsFromBinaryFile() { List<TagBound> tagBounds = new ArrayList<>(); for (String path : chunkFiles.getChunkFilePaths()) { try (FileInputStream fstream = new FileInputStream(path); ObjectInputStream ostream = new ObjectInputStream(fstream)) { while (true) { TagBound tagBound = (TagBound) ostream.readObject(); tagBounds.add(tagBound); } } catch (Exception e){ e.printStackTrace(); } } return tagBounds; }
问题原因与修复方案
核心问题
写入时用自定义的AppendableObjectOutputStream跳过了序列化流头,但读取时用标准ObjectInputStream会强制检查流头,导致解析失败。同时,追加写入多个对象时,后续对象缺少正确的流上下文,进一步引发异常。
修复步骤
自定义匹配写入逻辑的输入流
创建AppendableObjectInputStream类,跳过流头检查,对应写入时的操作:private static class AppendableObjectInputStream extends ObjectInputStream { public AppendableObjectInputStream(InputStream in) throws IOException { super(in); } @Override protected void readStreamHeader() throws IOException { // 跳过流头验证,匹配写入时的逻辑 } }修改读取方法
使用自定义输入流,并通过捕获EOFException终止循环(替代无限循环):public static List<TagBound> getAllTagBoundsFromBinaryFile() { List<TagBound> tagBounds = new ArrayList<>(); for (String path : chunkFiles.getChunkFilePaths()) { try (FileInputStream fstream = new FileInputStream(path); AppendableObjectInputStream ostream = new AppendableObjectInputStream(fstream)) { while (true) { try { TagBound tagBound = (TagBound) ostream.readObject(); tagBounds.add(tagBound); } catch (EOFException e) { // 文件读取完毕,退出循环 break; } } } catch (Exception e){ e.printStackTrace(); } } return tagBounds; }额外注意事项
- 确保
TagBound及其内部所有引用的对象都实现Serializable接口,否则会导致序列化失败。 - 保持写入后正确关闭流的逻辑,避免流状态混乱。
- 确保
内容的提问来源于stack exchange,提问作者Caniuss
相关产品推荐
相关产品推荐

