aa(Unicode) :6
呃(Unicode) :4
呃呃(Unicode) :6
a(UTF-8) :1
aa(UTF-8) :2
呃(UTF-8) :3
呃呃(UTF-8) :6
a(UTF-16) :4
aa(UTF-16) :6
呃(UTF-16) :4
呃呃(UTF-16) :6
在 Unicode 编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在 Unicode 中是不存在的字符,所以不应该出现在实际传输中。 Unicode 规范建议在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。
这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。
在 Java 中直接使用Unicode 转码时会按照UTF-16LE 的方式拆分,并加上 BOM。 如果采用 UTF-16 拆分,在 Java 中默认采用带有 BOM 的 UTF-16BE 拆分。
可能大部分人对UTF-8用的比较多,通过查资料得到如下结论:
UTF-8 使用一至四个字节为每个字符编码。128 个 ASCII 字符(Unicode 范围由 U+0000 至 U+007F)只需一个字节,带有变音符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及马尔代夫语(Unicode 范围由 U+0080 至 U+07FF)需要二个字节,其他基本多文种平面(BMP)中的字符(CJK属于此类-Qieqie注)使用三个字节,其他 Unicode 辅助平面的字符使用四字节编码。
所以在java下不能使用byte[]+StringBuffer读取字符:StringBuffer是针对char操作的(String也是)。读取byte时可能刚好把一个多字节的char分成前后两批加入StringBuffer。这样就破坏了char的完整性了。而如果你使用UTF-8编码的中文,你就会中招,导致乱码(其实是因为你的读取是由于byte失去原有顺序导致的,跟一般的乱码还不一样) 。
可以用StringBuffer + bufferedReader.readLine(),读出一行行后再加入StringBuffer。
或者用stringbuffer+reader.read(char[])的形式,毕竟错误是由byte[]造成,而不是StringBuffer。
总上所述:
Unicode和UTF-16:1个字符占2个字节(不管是哪国语言)
UTF-8:1个英文字符占1个字节,一个汉字(包括日文和韩文等)占3个字节
Java中的char默认采用Unicode编码,所以Java中char占2个字节