Search code examples
javabinaryfiles

Java Binary File Block Header


I am trying to read a binary file that I wrote with the FileOutputStream class. The class I am using to read it is a RandomAccessFile class.

When I inspect the file in a hex editor, there seems to be about 9 extra bytes in front of my own actual data. This data seems to be ignored when using the FileInputStream class to read, however with RandomAccessFile, it is not. I have done a bit of research, and I believe this is some kind of block header. However, I can find nothing specific and would like to ask what this block header consists of.

Here is some code that showcases this problem:

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();
    }


}
}

As you can see, RandomAccessFile does not return the same as ObjectInputStream, since it appears that ObjectInputStream ignores the mentioned block header.

Thank you.


Solution

  • ObjectOutputStream writes according to the (unimaginatively named) Object Serialization Stream Protocol.

    An hexdump of the file is:

    ac ed 00 05 77 04 00 00 01 2c
    

    broken into blocks:

    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
    

    With RandomAccessFile you'll have to skipBytes(4) (or – arguably better – check that the file header is in fact ac ed 00 05) and also handle the TC_BLOCKDATA.