使用字符集转换字节会导致字符串末尾的菱形?

问题描述

我目前将一个字符串存储为一个字节数组。但是,当我尝试使用以下代码使用 Charset 将字节转换回字符串时,最后我有菱形:

byte[] testbytes = "abc123".getBytes(); // tried getBytes("UTF-8"/StandardCharsets.UTF_8) too

Charset charset = Charset.forName("UTF-8"); // ISO-8859-1 has no diamonds
CharBuffer charBuffer = charset.decode( ByteBuffer.wrap( Arrays.copyOfRange(testbytes,testbytes.length) ) );

System.out.println("converted = " + String.valueOf(charBuffer.array()) );
// returns this - abc123����������

如果我将编码设置为 ISO-8859-1,它转换得很好。我认为这可能是源代码文件的编码,但在 Notepad++ 中打开它表明它也是 UTF-8。

我是否遗漏了什么,或者这只是 Android Studio 的 Logcat 窗口的问题?

- 编辑 1 -

进一步的测试表明,3 个字符串的结尾没有这个填充问题。如果您使用更长的字符串,Charset.decode 似乎会根据断点用 \u0000 值填充字符数组。

String.valueOf 最终会将填充的字符打印为菱形,同时创建新的 String 对象会删除填充,但是,由于敏感值,我根本不想使用 String 将字节数组转换为字符数组。

- 编辑 2 -

如果您再次调用 charset.decode() 似乎会发生上述情况,所以我猜有一个缓冲区被附加到但不确定在什么时候。尝试使用 charBuffer.clear() 进行清除,但第二个代码块的输出似乎相同,即 3 个字符 + 2 个空格 + 6 个新字符。

        String test1 = "123";
        byte[] test1b = test1.getBytes();
        char[] expected1 = test1.tochararray();
        CharBuffer charBuffer = charset.decode( ByteBuffer.wrap( test1b ) );
        char[] actual1 = charBuffer.array(); // size 3,correct

        String test2 = "123456";
        byte[] test2b = test2.getBytes();
        char[] expected2 = test2.tochararray();
        CharBuffer charBuffer2 = charset.decode( ByteBuffer.wrap( test2b ) );
        char[] actual2 = charBuffer2.array(); // size 11,padded with '\u0000' 0

解决方法

您是否尝试使用接收字节数组的 String 构造函数? 喜欢:

byte[] testbytes = "abc123".getBytes(StandardCharsets.UTF_8);
String stringDecoded = new String(testbytes,StandardCharsets.UTF_8);

也许它可以解决您的问题。