2016-01-21 94 views
12

所以Java中的'char'是2个字节。 (可从here进行验证。)Java如何将一个3字节的Unicode字符转换为char类型?

我有这样的示例代码:

public class FooBar { 
    public static void main(String[] args) { 
     String foo = "€"; 
     System.out.println(foo.getBytes().length); 
     final char[] chars = foo.toCharArray(); 
     System.out.println(chars[0]); 
    } 
} 

和输出如下:

3 
€ 

我的问题是,怎么没的Java适合3字节字符转换为char数据类型?顺便说一句,我正在与参数的应用:-Dfile.encoding = UTF-8

另外,如果我远一点编辑代码并添加以下语句:

File baz = new File("baz.txt"); 
final DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(baz)); 
dataOutputStream.writeChar(chars[0]); 
dataOutputStream.flush(); 
dataOutputStream.close(); 

最后文件“巴兹.txt“将只有2个字节,并且即使将其视为UTF-8文件,它也不会显示正确的字符。

编辑2: 如果我用UTF-16 BE编码打开文件“baz.txt”,我会在我的文本编辑器中看到€字符,这很有道理。

+3

Java在内部使用UTF-16。请参阅http://stackoverflow.com/questions/9699071/what-is-the-javas-internal-represention-for-string-modified-utf-8-utf-16 –

+0

字符不是字符;它更少 - 这是Java最大的问题之一。请参阅utf8everywhere.org获取关于它如何工作的完整说明。 –

回答

8

String.getBytes()使用平台的默认字符编码返回字节,该编码不需要匹配内部表示。

Java在每个字符的ram中使用2个字节,当字符使用UTF-8“串行化”时,它们可能会在生成的字节数组中产生一个,两个或三个字节,这就是UTF-8编码的工作原理。

你的代码示例使用的是UTF-8。 Java字符串使用UTF-16编码在内存中。不符合单个16位字符的Unicode代码点将使用称为代理对的2个字符对进行编码。

如果您没有将参数值传递给String.getBytes(),它将返回一个字节数组,其中的字符串内容使用底层操作系统的默认字符集进行编码。如果你想确保一个UTF-8编码数组,那么你需要使用getBytes(“UTF-8”)。

调用String.charAt()仅从String的内存存储中返回原始的UTF-16编码字符。

检查此链接:java utf8 encoding - char, string types

7

Java使用UTF-16(16位)的内存中表示。

即使它需要UTF-8中的三个字节,欧元符号也适用于此。

+1

所以一个字符总是UTF-16编码? –

+2

是的,这是一个问题,因为Unicode比这个大。一些Unicode代码点现在需要Java中的两个字符。因此,如果使用“整个目录”,“length”或“charAt”的结果可能并不完全令人满意。 – Thilo

+0

所以我传递的参数-Dfile.encoding = UTF-8并没有真正改变太多,我们可以说吗? –

相关问题