Java - CRC32.update() 在串联的 ByteBuffer 上

Java - CRC32.update() on concatenated ByteBuffer

我有以下功能:

   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());

无论我为字节数组分配什么值,getValue() 总是 returns 0 当我通过 byteBuffers 连接时。根据 ,这是连接字节缓冲区的有效方式。如果我只在单个 byteBuffer 上调用 put() (例如,如果我注释掉 byte[] test2 = {5,6,7,8}; 行,那么 getValue() 实际上 returns 是一个有效值。

这是连接 ByteBuffer 的方式的问题,update(ByteBuffer) 在连接的 ByteBuffers 上执行,还是其他原因?

您对 put 的调用已将 ByteBuffer 的位置提升到 CRC32.update().

没有剩余字节可读的程度

如果您只放置两个字节缓冲区之一,那么仍然有 4 个字节要读取用于 CRC 校验和(所有 4 个字节的值为 0)。

您需要在调用 checksum.update(contents) 之前将字节缓冲区的位置重置为零。您可以为此使用 rewindflip

contents.rewind();

contents.flip();

Flip 的作用与 rewind() 相同,但另外它将 ByteBuffer 的 limit 设置为翻转前的 position,因此如果您首先构造ByteBuffer 然后想从中读取,flip() 更正确,因为您没有 运行 从尚未写入的 ByteBuffer 部分读取的风险。

EJP 的回答很有见地,因为他指出您根本不需要连接字节缓冲区。

您也可以执行以下操作之一:

  • 用单独的字节缓冲区更新 CRC32
  • 使用ByteBuffer.put(byte[])直接将test1test2字节数组放入contentsByteBuffer
  • 完全跳过 ByteBuffers 并依次调用 CRC32.update(byte[])test1test2

您需要通过在放置(或从通道读取)之后调用 flip() 并在之后调用 compact() 来准备用于获取(或写入通道)的缓冲区。

但我完全不知道您为什么要串联 ByteBuffers。就这样

checksum.update(bbtest1);
checksum.update(bbtest2);

创建另一个数据副本没有任何优势,NIO 包含 scatter/gather 方法可同时对多个 ByteBuffers 进行操作。