Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitconverter for Java

Following the advice provided in the question https://stackoverflow.com/questions/1738244/what-is-the-java-equivalent-of-net-bitconverter I have begun implementing my own bitconverter for Java but am not getting equivalent results.

Could someone please guide me on what I might be doing incorrectly?

public static byte[] GetBytes(Integer value) {
    ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
    DataOutputStream stream = new DataOutputStream(byteStream);
    try {
        stream.writeInt(value);
    } catch (IOException e) {
        return new byte[4];
    }
    return byteStream.toByteArray();
}

byte[] result = BitConverter.GetBytes(1234); //JAVA: [0, 0, 4, -46]
byte[] result = BitConverter.GetBytes(1234); //C#: [210, 4, 0, 0]
like image 516
Maxim Gershkovich Avatar asked May 03 '11 06:05

Maxim Gershkovich


2 Answers

The C# BitConverter will use the endianness of the underlying achitecture. In most environments, it will be little-endian (as it is in your case). Java's DataOutputStream however will always write in big-endian ("the portable way"). You'll need to check the endianness of the machine and write accordingly if you want to match the behavior.

Also, bytes in java are signed so the output is just a cosmetic difference. The bit representation is the same so you don't need to worry about that.

To check the endianness of your machine, use the java.nio.ByteOrder.nativeOrder() method. Then use the java.nio.ByteBuffer instead where you may specify the byte order() and write the data.

You could then implement your method like this:

public static byte[] GetBytes(int value)
{
    ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder());
    buffer.putInt(value);
    return buffer.array();
}
like image 151
Jeff Mercado Avatar answered Oct 06 '22 01:10

Jeff Mercado


That is just endianness (-46 and 210 is because of Java's signed bytes, but that is just a UI thing). Either reverse the array contents, or use shift operations to write the int.

Note: the endianness that .NET emits depends on the platform. I would suggest using KNOWN ENDIANNESS in both cases; most likely by using shift operations from both. Or perhaps a better idea: just use a pre-canned, platform independent serialization format (for example: protocol buffers, which has good support on both Java and .NET/C#).

For example; if I was writing an int value to a byte[] buffer (starting at offset), I might use:

buffer[offset++] = (byte)value;
buffer[offset++] = (byte)(value>>8);
buffer[offset++] = (byte)(value>>16);
buffer[offset++] = (byte)(value>>24);

this is guaranteed little-endian, and similar code should work on any framework.

like image 38
Marc Gravell Avatar answered Oct 06 '22 01:10

Marc Gravell