File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes Write Binary File in Java to be read by a C Program and Vice Versa Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Write Binary File in Java to be read by a C Program and Vice Versa" Watch "Write Binary File in Java to be read by a C Program and Vice Versa" New topic
Author

Write Binary File in Java to be read by a C Program and Vice Versa

Freddy Wong
Ranch Hand

Joined: Sep 11, 2006
Posts: 959

Suppose that I'm trying to create a binary file created in Java to be read by a C program. Below is the code.



On my PC, it printed like this

unsigned byte=12
unsigned short=53760
unsigned int=4

which is incorrect.

Similarly I'm trying to create a binary file created in C to be read by a Java program. Below is the code.




On my PC, it printed like this

unsigned byte=12
unsigned short=10619
unsigned int=13763584

which again is incorrect.

Any pointers what might go wrong here?

Thanks in advance.


SCJP 5.0, SCWCD 1.4, SCBCD 1.3, SCDJWS 1.4
My Blog
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

You're assuming that sizeof(struct) is the sum of the sizes of the members (7 bytes) and they follow each other one after the other with no gaps; this is actually unlikely. Usually structs are padded to 4 or even 8-byte boundaries, depending on the compiler. I think most compilers these days would pack that struct into 8 bytes: one for the char, an unused byte, two for the short, and four for the int. Therefore when you read the data, it's aligned incorrectly, so you get weird numbers; and likewise with the Java code (which doesn't confirm that it reads the number of bytes it expects, either, and gets one more byte than the 7 it wants.)

So the sad truth is that the layout of the C struct is compiler dependent, and you'll have to determine what your compiler does in terms of padding, and then match it with your Java program. Once you do that, you should be fine.


[Jess in Action][AskingGoodQuestions]
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3649
    
  17

You can make things much easier for yourself by providing some sort of custom OutputStream.


Freddy Wong
Ranch Hand

Joined: Sep 11, 2006
Posts: 959

Thanks Ernest, I guess that explains why my code doesn't work and thanks Stephan for the code. It's a much nicer code that mine
Akil Kumar
Ranch Hand

Joined: Jun 08, 2009
Posts: 83
Ernest Friedman-Hill wrote:You're assuming that sizeof(struct) is the sum of the sizes of the members (7 bytes) and they follow each other one after the other with no gaps; this is actually unlikely. Usually structs are padded to 4 or even 8-byte boundaries, depending on the compiler. I think most compilers these days would pack that struct into 8 bytes: one for the char, an unused byte, two for the short, and four for the int. Therefore when you read the data, it's aligned incorrectly, so you get weird numbers; and likewise with the Java code (which doesn't confirm that it reads the number of bytes it expects, either, and gets one more byte than the 7 it wants.)

So the sad truth is that the layout of the C struct is compiler dependent, and you'll have to determine what your compiler does in terms of padding, and then match it with your Java program. Once you do that, you should be fine.


Hi Ernest,

Normally these padding or packing should be done at the C program. For instance if I were to read or write some data from the Java program through the socket to the C server program. Doing all these conversions in the Java program wouldn't be expensive?

As per standard how the data should be sent from the C program? Should it be in network byte order or it can be little endian?

Thanks,
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14432
    
  23

It doesn't really matter if you do things like adding or skipping padding at the side of the C program or at the side of the Java program - the important thing is that the two programs understand each other. Doing these things in Java is not much more expensive than in C.

There is no common standard that says you have to send the data in big or little endian order.

There are standard protocols for exchanging data, and if I had to do something like this, I'd first investigate those protocols before trying to re-invent the wheel myself. For example, Google protocol buffers look like a good way to do this. You define in a special specification language what you data looks like, and Google's tool generates some code in C++, Java or Python that you can use to make the programs talk to each other. You don't have to worry about the low-level details, such as what the format of the bytes that are sent across exactly is.


Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 8 API documentation
 
 
subject: Write Binary File in Java to be read by a C Program and Vice Versa