Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to read structured binary files with Java

I have to read a binary file in a legacy format with Java.

In a nutshell the file has a header consisting of several integers, bytes and fixed-length char arrays, followed by a list of records which also consist of integers and chars.

In any other language I would create structs (C/C++) or records (Pascal/Delphi) which are byte-by-byte representations of the header and the record. Then I'd read sizeof(header) bytes into a header variable and do the same for the records.

Something like this: (Delphi)

type   THeader = record     Version: Integer;     Type: Byte;     BeginOfData: Integer;     ID: array[0..15] of Char;   end;  ...  procedure ReadData(S: TStream); var   Header: THeader; begin   S.ReadBuffer(Header, SizeOf(THeader));   ... end; 

What is the best way to do something similar with Java? Do I have to read every single value on its own or is there any other way to do this kind of "block-read"?

like image 609
Daniel Rikowski Avatar asked Nov 10 '08 14:11

Daniel Rikowski


People also ask

Which class would be best to use to read a binary file into a Java object?

The preferred stream classes for processing binary files are ObjectInputStream and ObjectOutputStream.

How does Java handle binary data?

A binary literal is a number that is represented in 0s and 1s (binary digits). Java allows you to express integral types (byte, short, int, and long) in a binary number system. To specify a binary literal, add the prefix 0b or 0B to the integral value.


2 Answers

To my knowledge, Java forces you to read a file as bytes rather than being able to block read. If you were serializing Java objects, it'd be a different story.

The other examples shown use the DataInputStream class with a File, but you can also use a shortcut: The RandomAccessFile class:

RandomAccessFile in = new RandomAccessFile("filename", "r"); int version = in.readInt(); byte type = in.readByte(); int beginOfData = in.readInt(); byte[] tempId; in.read(tempId, 0, 16); String id = new String(tempId); 

Note that you could turn the responce objects into a class, if that would make it easier.

like image 193
Powerlord Avatar answered Sep 20 '22 18:09

Powerlord


If you would be using Preon, then all you would have to do is this:

public class Header {     @BoundNumber int version;     @BoundNumber byte type;     @BoundNumber int beginOfData;     @BoundString(size="15") String id; } 

Once you have this, you create Codec using a single line:

Codec<Header> codec = Codecs.create(Header.class); 

And you use the Codec like this:

Header header = Codecs.decode(codec, file); 
like image 38
Wilfred Springer Avatar answered Sep 19 '22 18:09

Wilfred Springer