简体   繁体   中英

Convert long to “unsigned, 4 byte integer in network byte order” with ByteBuffer

The protocol I'm using requires sending back the current position in a file as a "unsigned, 4 byte integer in network byte order". There are several questions on this, but they are assuming I'm using Integers, not Longs

I am attempting to port this to NIO's ByteBuffer so it can be sent in the socket channel:

long bytesTransfered = ... some number of bytes transfered...
//TODO: What does this actually do?
outBuffer[0] = (byte) ((bytesTransfered >> 24) & 0xff);
outBuffer[1] = (byte) ((bytesTransfered >> 16) & 0xff);
outBuffer[2] = (byte) ((bytesTransfered >> 8) & 0xff);
//TODO: Why does netbeans say this does nothing?
outBuffer[3] = (byte) ((bytesTransfered >> 0) & 0xff);

Are their any methods in ByteBuffer that accomplish this? Hopefully in a more obvious, self-descriptive way then the bit-shifting magic above?

Whether signed or unsigned, the bits are the same.

If you cast a long to an int , the JVM discards the high-order bits. The issue comes when promoting an int to a long : Java will sign-extend the value, filling in the high-order bits of the long with the most-significant bit of the int .

To resolve this problem, simply apply a mask to the long. The following should make this clear:

long value = Integer.MAX_VALUE + 1234L;
System.out.println("original value    = " + value);

int iValue = (int)value;
System.out.println("value as int      = " + iValue);
byte[] array = new byte[4];

ByteBuffer buf = ByteBuffer.wrap(array);
buf.putInt(0, iValue);

int iRetrieved = buf.getInt(0);
System.out.println("int from buf      = " + iRetrieved);

long retrieved = iRetrieved;
System.out.println("converted to long = " + retrieved);

retrieved = retrieved & 0xFFFFFFFFL;
System.out.println("high bytes masked = " + retrieved);

However , be aware that you still have only 32 bits. If the filesizes is greater than 4Gb you won't be able to fit it into 4 bytes (and if you have to worry about files > 2G, then you should worry about files > 4G).

That's exactly what ByteBuffer.putInt() is for. You say you're using long but you also only want to write four bytes, so you'll have to cast your long to int . Or else use putLong() and get 8 bytes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM