首页 > 开发 > Java > 正文

JAVA里字符编码的探索与理解

2024-07-13 09:54:52
字体:
来源:转载
供稿:网友
 今天终于把java里一个比较头痛的问题——字符编码弄清晰了,所以写一篇文章来纪念一下,也为大家提供一点自己的心得。

众所周知,java为了国际通用,用的是unicode来保存里面的字符。而unicode只是一个种字符集,字符的存储和表示要用到一定的字符编码格式,而与unicode对应的字符编码格式就是我们常看到的utf-8,utf-16等等,而utf-8是最常用的,所以人们常常把它和unicode等同起来(我以前就是这样的),这在某些情况下是没有错的,但这样的理解在java里就会产生一些混淆。我们用下面的程序来演示一下。

定义一个字符串

string name = "堂";

这个字符串就一个字符,把它取出来

char c_name = name.charat(0);

java里的char型是十六位的(两个字节),但是如果是用utf-8的话可能会不只两位(utf-8是变长存储的),那看来java本身并不是用utf-8来保存的,口说无凭,做个实验吧。
首先看看char里保存的内容

int low = (c_name) & 0xff;//取c_name的低位

int high = (c_name >> 8) & 0xff;//取c_name的高位

system.out.println(integer.tohexstring(high) + " " + integer.tohexstring(low));

结果是58 02

只有两个字节而已(16位),那么真正的utf-8编码的内容是什么呢,再看看吧。

为了方便,我写了一个辅助方法printbyte,作用是把一个byte数组的每个元素按照十六进制格式打印出来,同样为了方便,我把它作为静态方法。

public static void printbyte(byte[] bt)

{

for (int i = 0; i < bt.length; i++)

{

int hex = (int)bt[i] & 0xff;

system.out.print(integer.tohexstring(hex) + " ");

}

system.out.println(" length = "+bt.length);

}

byte[] utf_8 = name.getbytes("utf-8");

printbyte(utf_8);

结果是e5 a0 82 length = 3

哇,三个字节!看来java内部用的真不是utf-8,那用的是什么呢?utf-16?看一下便知。

byte[] utf_16 = name.getbytes("utf-16");

printbyte(utf_16);

结果是fe ff 58 02 length = 4,靠,四个字节了。咦?后面的低16位不正是和开始c_name的十六进制表示一样的吗?看来java真正的内部字符编码和utf-16有或多或少的联系。java内部究竟是用的什么字符编码呢?这个问题我也找了很久,后来在think in java 3rd的12章里看到一个例子出现了utf-16be,难道是它?

byte[] utf_16be = name.getbytes("utf-16be");

printbyte(utf_16be);

结果出来了:58 02 length = 2

哈哈,i got it!不多不少两个字节,内容也一样。果然是它。同时我在里面也看到,unicode的编码还有一个le,这里的be,le我想应该是bigendian和littleendian吧。

好了,java里字符的编码总算搞清楚了,这是本人的第一篇原创文章,可能很肤浅。如果有什么不对的地方请大家慷慨指教!谢谢。


上一篇:J2ME Web 服务入门

下一篇:javaCC学习笔记

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表