ByteBuffer,CharBuffer,String和Charset

min*_*ins 6 java bytebuffer character-encoding

我正在尝试根据字符集整理字符,它们在字节序列中的表示,以及如何在Java中将一个字符集转换为另一个字符集.我有些困难.

例如,

ByteBuffer bybf = ByteBuffer.wrap("Olé".getBytes());
Run Code Online (Sandbox Code Playgroud)

我的理解是:

  • 字符串始终以Java格式存储为UTF-16字节序列(每个字符2个字节,大端)
  • getBytes() 结果是相同的UTF-16字节序列
  • wrap() 保持这个顺序
  • bybf 因此是字符串的UTF-16大端表示 Olé

因此在这段代码中:

Charset utf16 = Charset.forName("UTF-16");  
CharBuffer chbf = utf16.decode(bybf);  
System.out.println(chbf);  
Run Code Online (Sandbox Code Playgroud)

decode() 应该

  • 解释bybf为UTF-16字符串表示
  • 将其"转换"为原始字符串Olé.

实际上不应该改变任何字节,因为一切都是UTF-16存储的,而UTF-16 Charset应该是一种"中性算子".但结果打印为:

??
Run Code Online (Sandbox Code Playgroud)

怎么可能?

附加问题:为了正确转换,似乎Charset.decode(ByteBuffer bb)需要bb是字符串的UTF-16大端字节序列图像.那是对的吗?


编辑:从提供的答案,我做了一些测试来打印ByteBuffer内容和chars通过解码获得.字节[编码用= "Olé".getBytes(charsetName)]打印在第一行组上,另一行是通过Charset#decode(ByteBuffer)用各种方法解码字节[with ]而获得的字符串Charset.

我还确认byte[]在Windows 7计算机上存储String的默认编码是windows-1252(除非字符串包含需要UTF-8的字符).

Default VM encoding: windows-1252  
Sample string: "Olé"  


  getBytes() no CS provided : 79 108 233  <-- default (windows-1252), 1 byte per char
     Decoded as windows-1252: Olé         <-- using the same CS than getBytes()
           Decoded as UTF-16: ??          <-- using another CS (doesn't work indeed)

  getBytes with windows-1252: 79 108 233  <-- same than getBytes()
     Decoded as windows-1252: Olé

         getBytes with UTF-8: 79 108 195 169  <-- 'é' in UTF-8 use 2 bytes
            Decoded as UTF-8: Olé

        getBytes with UTF-16: 254 255 0 79 0 108 0 233 <-- each char uses 2 bytes with UTF-16
           Decoded as UTF-16: Olé                          (254-255 is an encoding tag)
Run Code Online (Sandbox Code Playgroud)

Bev*_*ynQ 8

你大多是正确的.

java中的本机字符表示形式是UTF-16.但是,在将字符转换为字节时,您可以指定正在使用的字符集,或者系统使用它的默认值,每当我选中时,它通常都是UTF-8.如果您正在混合和匹配,这将产生有趣的结果.

例如,我的系统如下

System.out.println(Charset.defaultCharset().name());
ByteBuffer bybf = ByteBuffer.wrap("Olé".getBytes());
Charset utf16 = Charset.forName("UTF-16");
CharBuffer chbf = utf16.decode(bybf);
System.out.println(chbf);
bybf = ByteBuffer.wrap("Olé".getBytes(utf16));
chbf = utf16.decode(bybf);
System.out.println(chbf);
Run Code Online (Sandbox Code Playgroud)

产生

UTF-8
佬쎩
Olé

因此,如果UTF-16是默认字符集,则此部分才正确
getBytes() result is this same UTF-16 byte sequence.

因此,要么总是指定您正在使用的最安全的字符集,因为您将始终知道发生了什么,或者始终使用默认值.

  • 大多数 Windows 系统并不默认使用 utf-8。另外,不确定“UTF-16 ish”是什么意思。java使用UTF-16。 (2认同)

use*_*421 7

字符串始终以Java格式存储为UTF-16字节序列(每个字符2个字节,大端)

是.

getBytes()结果是相同的UTF-16字节序列

不会.无论是什么,它都会将UTF-16字符编码到平台默认字符集中.已过时.

wrap()维护这个序列

wrap() 保持一切.

因此,bybf是字符串Olé的UTF-16大端表示

不.它包装了平台原始字符串的默认编码.

decode()应该

  • 将bybf解释为UTF-16字符串表示

不,见上文.

  • "将"转换为原始字符串Olé.

除非平台的默认编码是"UTF-16".