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)
之前将字节缓冲区的位置重置为零。您可以为此使用 rewind
或 flip
:
contents.rewind();
或
contents.flip();
Flip 的作用与 rewind()
相同,但另外它将 ByteBuffer 的 limit
设置为翻转前的 position
,因此如果您首先构造ByteBuffer 然后想从中读取,flip()
更正确,因为您没有 运行 从尚未写入的 ByteBuffer 部分读取的风险。
EJP 的回答很有见地,因为他指出您根本不需要连接字节缓冲区。
您也可以执行以下操作之一:
- 用单独的字节缓冲区更新 CRC32
- 使用
ByteBuffer.put(byte[])
直接将test1
和test2
字节数组放入contents
ByteBuffer
- 完全跳过 ByteBuffers 并依次调用
CRC32.update(byte[])
和 test1
和 test2
。
您需要通过在放置(或从通道读取)之后调用 flip()
并在之后调用 compact()
来准备用于获取(或写入通道)的缓冲区。
但我完全不知道您为什么要串联 ByteBuffers
。就这样
checksum.update(bbtest1);
checksum.update(bbtest2);
创建另一个数据副本没有任何优势,NIO 包含 scatter/gather 方法可同时对多个 ByteBuffers
进行操作。
我有以下功能:
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 连接时。根据 byte[] test2 = {5,6,7,8};
行,那么 getValue() 实际上 returns 是一个有效值。
这是连接 ByteBuffer 的方式的问题,update(ByteBuffer) 在连接的 ByteBuffers 上执行,还是其他原因?
您对 put
的调用已将 ByteBuffer 的位置提升到 CRC32.update()
.
如果您只放置两个字节缓冲区之一,那么仍然有 4 个字节要读取用于 CRC 校验和(所有 4 个字节的值为 0)。
您需要在调用 checksum.update(contents)
之前将字节缓冲区的位置重置为零。您可以为此使用 rewind
或 flip
:
contents.rewind();
或
contents.flip();
Flip 的作用与 rewind()
相同,但另外它将 ByteBuffer 的 limit
设置为翻转前的 position
,因此如果您首先构造ByteBuffer 然后想从中读取,flip()
更正确,因为您没有 运行 从尚未写入的 ByteBuffer 部分读取的风险。
EJP 的回答很有见地,因为他指出您根本不需要连接字节缓冲区。
您也可以执行以下操作之一:
- 用单独的字节缓冲区更新 CRC32
- 使用
ByteBuffer.put(byte[])
直接将test1
和test2
字节数组放入contents
ByteBuffer - 完全跳过 ByteBuffers 并依次调用
CRC32.update(byte[])
和test1
和test2
。
您需要通过在放置(或从通道读取)之后调用 flip()
并在之后调用 compact()
来准备用于获取(或写入通道)的缓冲区。
但我完全不知道您为什么要串联 ByteBuffers
。就这样
checksum.update(bbtest1);
checksum.update(bbtest2);
创建另一个数据副本没有任何优势,NIO 包含 scatter/gather 方法可同时对多个 ByteBuffers
进行操作。