Reputation: 15008
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?
Upvotes: 1
Views: 6976
Reputation: 646
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).
Upvotes: 6
Reputation: 310913
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.
Upvotes: 3