[java] Write/Read Binary Data of/to a class

Started by
18 comments, last by Halsafar 18 years, 4 months ago
Okay I found two examples of using binary IO. One was reading and the other was writing -- both only used ints. Now lets say I create a class called A and I want to write it to file. This is an easy task in C++, but I'm not sure how I can tell Java to write the info at the memory location of class (A) to the file. Likewise, if I can pull the above off, I can imagine that reading it back won't be so easy. Unless telling the DataInputStream to take n (bytes, size of A) and cast it into class A. Edit: I'd like to point out that the file being read from will be created by C++ and Java, so they need to work together on this one. I know already from some reading that Java is BIG_ENDIAN and C++ is LITTLE_ENDIAN. But Java can read in bytes in the reverse order by changing a bytebuffer flag. I am not sure if it can write in the reverse order as well. Unless there is a way to write a C++ DLL to do both the read and write. I thought about it but then got lost in the cross-language concept. How would C++ read it and leave Java with all the data stored nicely. [Edited by - Halsafar on November 29, 2005 4:22:11 PM]
Advertisement
Quote:Original post by Halsafar
Now lets say I create a class called A and I want to write it to file.

ObjectOutputStream?

Quote:I know already from some reading that Java is BIG_ENDIAN and C++ is LITTLE_ENDIAN.
But Java can read in bytes in the reverse order by changing a bytebuffer flag. I am not sure if it can write in the reverse order as well.


Read the Inputstream into a ByteBuffer, and change the endian encoding using ByteBuffer.order(ByteBuffer.BIG_ENDIAN || ByteBuffer.LITTLE_ENDIAN).

Quote:How would C++ read it and leave Java with all the data stored nicely.

Your dll file could read the file, and pass it upwards through a JNI interface. But as you can see above, Java has a built in alternative.
www.aidanwalsh(.net)(.info)
You should use ByteBuffer and FileChannel from the java.nio.* and java.nio.channels.* packages. That way you can set the ByteOrder on the ByteBuffer then read directly into the ByteBuffer using the FileChannel. ByteBuffer also has primitive gettors attached which will make getting your info easier.
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][LWJGL Tutorials for NeHe][LWJGL Wiki][jMonkey Engine]
A simple way to handling byte files that are both used by C++ and java is

ImageInputStream

The drawback is that I think it is only available since Java 5 which is not yet well supported everywhere.
If I use ObejctOutputStream to write data to file.
I have a good feeling I won't be able to read it back in with C++.
After reading the API doc you posted, it sounds like Java adds a lot of Java specific stuff to the file.

ImageInputStream, ImageOutput stream sound like they may work. But I'm not sure...

Java and C++ both need to be able to read/write.
Work at the binary level - ByteArrayOutputStream and ByteArrayInputStream, caring for the ByteOrder when reading/writting.

I don't know the data you're storing, but depending on what it is, XML would be a nice communication layer for this system.

Son Of Cain

[Edit: Use ByteBuffer and ByteOrder when controlling the endianness of the array, as described by aidan_walsh's post]
a.k.a javabeats at yahoo.ca
Its a map file format for the game in design.
The map editor is being made in Java, since it also needs to be cross-platform and requires a heavy GUI, we decided Java would simply be the easiest choice for a cross-platform widget system.

Thanks for the help everyone.
I'll give the ByteArrayOutput/InputStream a shot. I'll post if I run into any more problems.
Okay I have no idea how to convert an Object of any type to a byte array which I can use to store in a ByteArrayOutputStream, switch the endian, and save to file.

Honestly I cannot figure out to use these things properly. I'm reading the API's for them but they provide no sample.

Once I do get an Object into a ByteArrayOutputStream, how to I write the bytes to a file?
You can not get a pointer to a Java object like you do in C++. Besides, is it fool proof even in C++ to read write classes/structs. Will there not be alginment and layout issues on different computers.

What you have to do is write all the member variables of your java object using a DataOutputStream. You can only write primitives so any objects in the data structure need to write it self to the stream. Then you've got to parse this file back in c++. Creating the c++ object and filling in its member variables.

Seems to me your a bit naive about how hease this would be :) (Or I'm clueless and don't know what I'm talking about, wich might be true)
The way I see it...

public interface BinaryPersistent {    byte[] toBytes();  void read(byte[] data);}public class MyBinaryClass implements BinaryPersistent {    public byte[] toBytes() {    ByteBuffer buf = ByteBuffer.allocate(1024);    buf.setShort(0);    buf.setXXX(x); // use setters to write data    // order buffer    return buf.array();  }  public void read(ByteBuffer buffer) {    // get data using getXXX() methods on the buffer;  }}


The only way to send an object to a file is through Object Input/Output streams, but you won't be able to recover this information on the C++ side (obviously... but I'm not sure if JNI could handle it?)

Apart from that, I suggest you use a model like the one above... To work in both Java and C++ at binary level, in such a manner that both applications output the same binary content.

Son Of Cain
a.k.a javabeats at yahoo.ca

This topic is closed to new replies.

Advertisement