Java与Swift实现CRC32校验时输出值不一致问题咨询
CRC32校验值Java与Swift端计算结果不一致问题解答
问题背景
你当前使用Java内置的java.util.zip.CRC32和Swift的CryptoSwift库计算同一份二进制数据的CRC32校验和,出现两端结果不一致的问题,核心原因可从以下几个方向排查:
排查&修复方案
首先确认Java端API调用是否正确
你贴出的Java伪代码存在两处明显的API使用错误:java.util.zip.CRC32的update方法为void返回类型,无法直接赋值给long变量- 分块更新的
update重载需要三个参数update(byte[] 数组, int 起始偏移量, int 计算长度),你当前的传参把数据长度当成偏移量传入,会导致实际未计算任何有效数据,甚至抛出数组越界异常
正确的Java代码写法如下:
private void transferFileData(short index, byte[] data, long dataSize) { CRC32 crc32 = new CRC32(); // 传入完整数据计算,偏移量为0,计算长度为dataSize crc32.update(data, 0, (int) dataSize); // 调用getValue()获取最终校验值 long crc = crc32.getValue(); System.out.println("CRC32 : " + crc); }确认两端CRC32算法参数一致
Java内置的java.util.zip.CRC32使用标准IEEE CRC32参数:
多项式:0xEDB88320、初始值:0xFFFFFFFF、最终异或值:0xFFFFFFFF、输入输出均开启位反转
部分版本的CryptoSwift库的默认crc32()方法参数可能和上述标准不一致,可手动指定参数计算:import CryptoSwift func crc32Func(_ item:[Int8] ) { // 显式将有符号Int8转成无符号UInt8,避免符号转换错误 let uint8Bytes = item.map { UInt8(bitPattern: $0) } // 手动指定标准IEEE CRC32参数 let crc32 = uint8Bytes.crc32( polynomial: 0xEDB88320, initialValue: 0xFFFFFFFF, finalXor: 0xFFFFFFFF, reflectInput: true, reflectOutput: true ) // 转成UInt64打印,和Java侧long类型的输出格式对齐 print("checksum == \(UInt64(crc32))") }排除类型转换误差
Swift侧的[Int8]是有符号字节数组,转成无符号字节处理时如果直接用UInt8($0)而不是UInt8(bitPattern: $0),会导致负数值转换失败,直接抛出异常或得到错误的字节值,必须使用bitPattern构造器做无符号转换。
另外Java侧返回的校验值是long类型存储的无符号32位整数,Swift侧默认返回的是UInt32类型,转成有符号Int打印时如果最高位为1会得到负数或错误的正数,转成UInt64打印即可和Java侧结果对齐。
内容的提问来源于stack exchange,提问作者Mograin2020
相关产品推荐
相关产品推荐

