Java二进制文件块标头

时间:2018-02-14 22:50:04

标签: java binaryfiles

我正在尝试读取我使用FileOutputStream类编写的二进制文件。我用来读它的类是RandomAccessFile类。

当我在十六进制编辑器中检查文件时,在我自己的实际数据前面似乎有大约9个额外字节。使用FileInputStream类读取时,这些数据似乎被忽略,但是对于RandomAccessFile,它不是。我做了一些研究,我相信这是一种块头。但是,我找不到具体的内容,并想问这个块头是什么。

以下是一些展示此问题的代码:

import java.io.*;

public class Main {

public static void main(String[] args) {
    String path = "C:\\Users\\Fran\\Desktop\\test.bin"; //You should change this to a valid path on your computer
    try {
        FileOutputStream fstream = new FileOutputStream(path);
        ObjectOutputStream ostream = new ObjectOutputStream(fstream);

        ostream.writeInt(300);

        ostream.close();
        fstream.close();

        FileInputStream fIn = new FileInputStream(path);
        ObjectInputStream oIn = new ObjectInputStream(fIn);

        System.out.println(oIn.readInt());
        oIn.close();
        fIn.close();

        RandomAccessFile randomAccessFile = new RandomAccessFile(path,"r");

        System.out.println(randomAccessFile.readInt());

        randomAccessFile.close();

    } catch (Exception e){
        e.printStackTrace();
    }


}
}

正如您所看到的,RandomAccessFile不会返回与ObjectInputStream相同的内容,因为看起来ObjectInputStream忽略了所提到的块头。

谢谢。

2 个答案:

答案 0 :(得分:0)

你的代码毫无意义。如果您使用ObjectOutputStream进行书写,则必须使用ObjectInputStream进行阅读。

这是Java对象序列化工作。如果不使用为此目的提供的工具,您不能指望阅读它。

您这里只使用writeInt()readInt(),因此不清楚为什么要使用序列化。如果您没有使用writeObject()readObject()和朋友,那么您应该使用DataInput/OutputStream,它没有叠加协议。或者他可以使用DataOutputStream,您可以谨慎使用RandomAccessFile

答案 1 :(得分:-1)

ObjectOutputStream根据(缺乏想象力的名称)Object Serialization Stream Protocol写作。

文件的hexdump是:

ac ed 00 05 77 04 00 00 01 2c

分成块:

ac ed       -> magic number      java.io.ObjectStreamConstants.STREAM_MAGIC
00 05       -> version 5         java.io.ObjectStreamConstants.STREAM_VERSION
77 04       -> block of 4 bytes  java.io.ObjectStreamConstants.TC_BLOCKDATA + length
00 00 01 2c -> the int32 300

使用RandomAccessFile,您必须skipBytes(4)(或者 - 可以说更好 - 检查文件标题实际上是ac ed 00 05)并处理TC_BLOCKDATA