问题
I have the following function:
byte[] test1 = {1,2,3,4};
byte[] test2 = {5,6,7,8};
ByteBuffer bbtest1 = ByteBuffer.wrap(test1).order(ByteOrder.LITTLE_ENDIAN);
ByteBuffer bbtest2= ByteBuffer.wrap(test2).order(ByteOrder.LITTLE_ENDIAN);
ByteBuffer contents = ByteBuffer.allocate(bbtest1.limit() + bbtest2.limit());
contents.put(bbtest1);
contents.put(bbtest2);
CRC32 checksum = new CRC32();
checksum.update(contents);
System.out.println(checksum.getValue());
No matter what values I assign my byte arrays, getValue() always returns 0 when I have concatenated by byteBuffers. According to this thread, this is a valid way of concatenating byteBuffers. If I only call put() on a single byteBuffer (for example if I comment out the line byte[] test2 = {5,6,7,8};
then getValue() actually returns a valid value.
Is this an issue with the way the ByteBuffers are concatenated, update(ByteBuffer) performs on concatenated ByteBuffers, or maybe something else altogether?
回答1:
Your calls to put
have advanced the position of the ByteBuffer to the point that there is no byte left to read from it for CRC32.update()
.
If you only put one of the two byte buffers, then there will still be 4 bytes to read for the CRC checksum (all 4 have the value 0).
You need to reset the position of your bytebuffer to zero before calling checksum.update(contents)
. You can use rewind
or flip
for that:
contents.rewind();
or
contents.flip();
Flip does the same as rewind()
, but additionally it sets the limit
of the ByteBuffer to the position
it had before flipping, so if you first constructed the content of the ByteBuffer and then want to read from it, flip()
is more correct, as you don't run the risk of reading from parts of the ByteBuffer that you didn't yet write into.
EJP's answer is insightful, as he points out that you don't need to concatenate byte buffers at all.
You can alternatively do one of:
- update the CRC32 with the individual ByteBuffers
- use
ByteBuffer.put(byte[])
to directly put thetest1
andtest2
byte arrays in thecontents
ByteBuffer - skip ByteBuffers altogether and call
CRC32.update(byte[])
withtest1
andtest2
in sequence.
回答2:
You need to prepare the buffer for getting (or writing to a channel) by calling flip()
after the puts (or reads from a channel), and compact()
it afterwards.
But I don't know why you're concatenating ByteBuffers
at all. Just do
checksum.update(bbtest1);
checksum.update(bbtest2);
There's no advantage to creating yet another copy of the data, and NIO contains scatter/gather methods to operate on multiple ByteBuffers
at once.
来源:https://stackoverflow.com/questions/48257336/java-crc32-update-on-concatenated-bytebuffer