在google云存储项目中工作,我正在尝试计算Crc32c值并通过crc32c算法获取long值返回的base64编码。使用
计算crc32c I' mhttps://github.com/GoogleCloudPlatform/crc32c-java/blob/master/src/com/google/cloud/Crc32c.java
Crc32c crc32c = new Crc32c();
crc32c.update(byteSource.read(), 0, byteArrayLength);
long crcValue = crc32c.getValue();
byte[] bArray = String.valueOf(crcValue).getBytes();
String mEncodedCrc = BaseEncoding.base64().encode(bArray);
// GCSReturnedCrc是谷歌云存储返回的编码字符串
assertEquals(GCSReturnedCrc, mEncodedCrc);
//结果
java.lang.AssertionError: expected [MjY0MDc0ODQwNQ==] but found [nWafdQ==]`
其他相关链接:https://developers.google.com/storage/docs/hashes-etags#_JSONAPI
答案 0 :(得分:3)
您预期的哈希值太长; CRC32C定义为4个字节,但Google Crc32c实现返回一个长整数。这样做是为了与java.util.zip.Checksum
兼容,并避免在将4字节数量放入signed int中时出现签名问题。相反,您必须通过以下方法删除前四个前导字节:
Arrays.copyOfRange(Longs.toByteArray(crcValue), 4, 8);
我还打开了针对crc32c-java的pull请求,这有助于避免将来出现此问题:
答案 1 :(得分:1)
我有点困惑。您对base32编码CRC32C哈希值long
的字符串形式进行了base64。这是真的正确吗?对我来说这似乎不太可能,因为base64编码的主要原因是因为它的不是以可读的形式,例如String
。您似乎更有可能对CRC32C哈希本身的4个字节进行base64编码(它是一个32位哈希函数)。
你可以这样:
...
byte[] crcBytes = Ints.toByteArray((int) crc32c.getValue());
// byte[] crcBytes = crc32c.getValueAsBytes(); (method that was just added)
String base64 = BaseEncoding.base64().encode(crcBytes);
仅供参考,我们在Guava 18中releasing Hashing.crc32c()
,这应该会让这更容易。
byte[] crc32c = byteSource.hash(Hashing.crc32c()).asBytes();
String base64 = BaseEncoding.base64().encode(crc32c);
答案 2 :(得分:0)
你可以自己尝试一下:当编码值不匹配时,为什么不对它们进行解码并查看它们:
Long.parseLong(new String(BaseEncoding.base64().decode("MjY0MDc0ODQwNQ==")))
返回2640748405
。这看起来很好。
BaseEncoding.base64().decode("nWafdQ==")
以十六进制9D,66,9F,75返回字节,并将它们转换回字符串取决于所使用的字符集。使用UTF-8,您将获得�f�u
。如果没有字符集,则会得到一个代表数字的String
。
OTOH您的代码段看起来很好......所以启动调试器或添加一些调试输出。
顺便说一下,我建议避免像String#getBytes
这样的依赖于语言环境的方法。