Search code examples
javanetwork-programmingcastinglong-integerunsigned

Writing unsigned int of 4 bytes over network


I have problem writing an unsigned 4 bytes int in java.

Either writing a long value in java has different result on 64 bit MacOS and 32 bit Linux (Ubuntu) OR Writing to network a 4 byte unsigned int has a problem.

The following call works perfectly on my local OSX

writeUInt32(999999,outputstream)

Reading it back gives me 999999

However when the application is deployed to a network writing a long value results in some other random number (I assume the endian has been switched?) and reading it gives me some other large number.

---------- The complete method stack is as below---------------

public void writeUInt32(long uint32,DataOutputStream stream) throws IOException {
        writeUInt16((int) (uint32 & 0xffff0000) >> 16,stream);
        writeUInt16((int) uint32 & 0x0000ffff,stream);
    }

public void writeUInt16(int uint16,DataOutputStream stream) throws IOException {
        writeUInt8(uint16 >> 8, stream);
        writeUInt8(uint16, stream);
    }

public void writeUInt8(int uint8,DataOutputStream stream) throws IOException {
        stream.write(uint8 & 0xFF);
    }

Edit: To add to the confusion writing to a file and then transporting it over the network sends me the correct value! So when outputstream points to a local file then it writes the correct values but when outputstream points to a ByteArrayOutputStream then the long value written is wrong.


Solution

  • Just use DataOutput/InputStream.

    To write, cast your long to int

    public void writeUInt32(
          long uint32,
          DataOutputStream stream
        ) throws IOException
    {
        stream.writeInt( (int) uint32 );
    }
    

    On read, use readInt, assign to long and mask top 32 bits to get unsigned value.

    public long readUInt32(
          DataInputStream stream
        ) throws IOException
    {
        long retVal = stream.readInt( );
    
        return retVal & 0x00000000FFFFFFFFL;
    }
    

    EDIT

    From your questions, looks like you are confused about Java cast conversions and promotions for primitive types.

    Read this section of Java Spec on Conversions and Promotions: http://java.sun.com/docs/books/jls/third_edition/html/conversions.html