Sign in to follow this  
TempHolder

HUGE JAVA/C++ PROBLEM!

Recommended Posts

TempHolder    100
Hello I am in desperate need of help. I created a file format in Java using its DataOutputStream, this writes a map format I made, and it starts of with a integer that holds the number of floorpanels. When I save the work in the application I made, I can load the data back up easily using DataInputStream and it gives me the correct data I want. The problem is the format is to be used in a C++ Application. When I use fstream to read the binary data from the Java Programs data, it doesnt read right. I try to first read the integer I saved which is the very first thing in the file with fstream and i get 50331648, when it should be equal to 4. I was wondering if anyone knows what the problem might be?, My code works when I try to load the file with the Java Application itself, and my C++ code works when I tested it making a file in C++. If anyone can help me it would be greatly appreciated, possibly a sample source code of this same problem. TY!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
50331648 in binary = 0000 0011 0000 0000 0000 0000 0000 0000

if we reverse the bytes, this becomes 0000 0000 0000 0000 0000 0000 0000 0011

But that is 3, which means it is still off by one...still, I can't help but think that byte order is part of the problem. Note that DataOutputStream uses the same byte order on any machine, and this byte order might not match your machine's native order, so for platform independence you should define the byte order in your map file as well. Also are you sure the integer is 4 and not 3?

Share this post


Link to post
Share on other sites
Nychold    292
Download a hex editor and go to town on the files you write. The easiest and best answers to file questions can be found in the actual file itself. Writing programs which expect certain kinds of values, and certain kinds of byte order, and certain kinds of alignments just cause headaches more often than not. ^^

Share this post


Link to post
Share on other sites
ben_02    139
Read the specification of DataOutputStream. It says, for example:

void writeInt(int v)
Writes an int to the underlying output stream as four bytes, high byte first.

It works backwards.

Share this post


Link to post
Share on other sites
TempHolder    100
hey it is suppose to be 3 my bad, so how could i convert that into a the acutal number 3 in C++?

And also what would be best to fix this problem with Java or C++?, if so tell me how I might fix it with whichever.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
To read an integer, you can read one byte at a time and then assemble them into the integer using bitwise operations.

Share this post


Link to post
Share on other sites
Quote:
Original post by TempHolder
hey it is suppose to be 3 my bad, so how could i convert that into a the acutal number 3 in C++?

And also what would be best to fix this problem with Java or C++?, if so tell me how I might fix it with whichever.


Use std::bitset?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Try writing in XML?

at least it's easy to read and probably not THAT much slower to read in.

Share this post


Link to post
Share on other sites
ZedFx    176
Warning: Completely Non-Cross-Platform solution

int a;
a << your_stream;
_asm mov eax, a
_asm bswap eax
_asm mov a, eax

EDIT: x86 only, xml is a far better solution.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Read one byte at a time, store them in b1, b2, b3, and b4

You can build your number from the bytes like this:

int x = 0;
x |= b1 <

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Err my post got messed up, I'll try that again...

Read one byte at a time, store them in b1, b2, b3, and b4

You can build your number from the bytes like this:

int x = 0;
x |= b1 << 24;
x |= b2 << 16;
x |= b3 << 8;
x |= b4;

Share this post


Link to post
Share on other sites
s_p_oneil    443
It would be better to write your own macros or inline functions, like these (which should work both in Java and C++):


inline int swap_bytes(int n)
{
// For better performance, you can drop the first and last & operation
// For better readability, it's nice to leave them there
return ((n >> 24) & 0x000000FF) |
((n >> 08) & 0x0000FF00) |
((n << 08) & 0x00FF0000) |
((n << 24) & 0xFF000000);
}

inline short swap_bytes(short n)
{
return ((n >> 08) & 0x00FF) |
((n << 08) & 0xFF00);

}




EDIT: This solution should be faster than reading 1 byte at a time, but you said performance is not an issue, so either method should work fine.

Share this post


Link to post
Share on other sites
Rabbi    130
Why not try formating the file in ASCII? So if you want to have an integer at the start, then save it as a ASCII number. Then when loading the file in C++ use the std::atoi function in <cstring> to make the ASCII character into an integer.

Share this post


Link to post
Share on other sites
risingdragon3    382
I suggest you use an ASCII file.

However, if you insist...

the root cause of the problem is that Java uses a different endian-ness then x86. x86 is little endian; Java (apparently) is big endian. Therefore, you must always flip the order of bytes for everything you read in, including floats.

Just read in the bytes, flip the order, and cast to a float.

Note that this does not necessarily always work. You are relying on the tenaious fact that Java and C++ happen to use the same size and representation for a float. Seriously, just use an ASCII file format.

Share this post


Link to post
Share on other sites
ZQJ    496
The alternative portable way of doing it is to read the Java representation into a set of bytes, extract the mantissa, exponent and sign and reconstruct using the ldexp() function. You'll have to handle special cases like NAN and infinity yourself though.

Share this post


Link to post
Share on other sites
Quote:
Original post by TempHolder
Ok but can anyone give me a working example on how to reconstruct a float with 4 bytes?, because it isnt as easy as the interger when I tried it.


It is as easy as with an integer. A float is 4 bytes too. So instead of reading a float, you read an integer, then process it using s_p_oneil's code, then you use this little one-line inlined function:


inline float from_int(int i)
{
return *((float *)(&i));
}


First, it takes the address of i and modify the type of the pointer to (float*). Then it dereference the pointed variable (which end up beeing a float).

This is not a cast from int to float, because the binary value don't change.

HTH,

Share this post


Link to post
Share on other sites
Enigma    1410
Quote:
Original post by private_ctor
//A slow, technically undefined swap method between bytes would be
b[0] ^= b[3] ^= b[0] ^= b[3];
b[1] ^= b[2] ^= b[1] ^= b[2];

Fixed.

Enigma

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this