转换为UTF-8字符串的JavaL不同的大十进制值具有相同的值

Ste*_*ane 0 java utf-8 bigdecimal

作为与Avro玩乐的一部分,我发现了以下内容:

new String(new BigDecimal("1.28").unscaledValue().toByteArray(), Charset.forName("UTF-8"))
.equals(
new String(new BigDecimal("1.29").unscaledValue().toByteArray(), Charset.forName("UTF-8")))
-> true !!!!!!!!


DatatypeConverter.printBase64Binary(new BigDecimal("1.28").unscaledValue().toByteArray())
.equals(
DatatypeConverter.printBase64Binary(new BigDecimal("1.29").unscaledValue().toByteArray()))
-> false (as expected)
Run Code Online (Sandbox Code Playgroud)

new String(new BigDecimal("1.26").unscaledValue().toByteArray(), Charset.forName("UTF-8"))
.equals(
new String(new BigDecimal("1.27").unscaledValue().toByteArray(), Charset.forName("UTF-8")))
-> false (as expected)
Run Code Online (Sandbox Code Playgroud)

有人可以向我解释发生了什么事吗?看起来像1.27是截止.理想情况下,我需要

new String(new BigDecimal("1.28").unscaledValue().toByteArray(), Charset.forName("UTF-8"))
Run Code Online (Sandbox Code Playgroud)

适用于每个BigDecimal值.

Jon*_*eet 5

有人可以向我解释发生了什么事吗?

是的,你在滥用你的数据.结果BigDecimal.toByteArray()不是字符串的UTF-8编码的表示,所以你不应该尝试这种方式转换为字符串.

如果它们基本上无效,则可以通过UTF-8将一些不同的字节数组"解码"为字符串.如果你看看new BigDecimal("1.28").unscaledValue().toByteArray()1.29 的结果,你会发现它们是无效的,所以两者都解码为包含"?"的字符串.但是,如果你这样做,那么你做错了.

有问题的两个字节数组是{0x00,0x80}和{0x00,0x81}.它的第一个字节将被解码为U + 0000,它的第二个字节是字符的UTF-8编码的开始,但它不完整 - 所以解码器使用?.所以两个字符串都是"\0?".

如果要将a转换BigDecimal为字符串,只需调用即可toString().如果要将任意二进制数据表示为字符串,请使用base64或hex,或者设计用于将任意二进制数据表示为字符串的类似编码方案.UTF-8旨在将任意文本数据表示为二进制数据.