Java - CRC32.update() on concatenated ByteBuffer

China☆狼群 提交于 2019-12-24 09:25:26

问题


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 the test1 and test2 byte arrays in the contents ByteBuffer
  • skip ByteBuffers altogether and call CRC32.update(byte[]) with test1 and test2 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!