现在的位置: 首页 > 综合 > 正文

主题:java编码解惑

2018年05月11日 ⁄ 综合 ⁄ 共 1610字 ⁄ 字号 评论关闭

上篇关于java编码问题的总结发布之后,回头到家自己一想,只是按照自己的思路去记录了一下个人编码问题当中遇到的问题,分析还不够详细。今日提笔如下,希望大家给予点评.

1.先解释几个重要的概念:

<1>.字符集:一个字符的集合,仅仅如此,它只包含某某某些字符,没有别的意义。

<2>.编码字符集:即我们通常意义上要表示的 字符集,它将字符与一个数字一一对应(计算机只认数字)。例如 个人自定义编码字符集 whd 如下:

工:0X1001

人:0X1002

是:0X1003

好:0X1004

样:0X1005

的:0X1006

<3>.编码方式:即我们经常说的gbk gb2312 utf-8等等这样的所谓的编码。其实编码是一个动作,包含了编码字符集和编码方式,二者结合即构成“编码”。而并不是我们通常意义上理解的名词。

例如UTF-8编码这里我做一个个人理解的解释:使用单字节或双字节或三字节 三种方式(按情况需要所定)对unicode字符集进行转换的一种可变长编码。

 

2.或许大家对上面的解释还有些不明白。不着急下面一一详细分析。如果一个字符集有256个字符,那么在单字节的内存管理系统当中,每个字符用一个字节存储,足够。也就是说一个字符对应一个8位的二进制值(这个值我们称为码点)。但是如果字符集比较大,8位的单字节存储系统每个字节不足以唯一标识一个字符。这样就需要多个字节存储一个字符。

这样的情况下,例如65536个字符,最后一个字符就需要16位二进制位标识。那么第一个字符肯定不需要这么多内存位单元来标识。这样如果采用定长双字节的编码方式(例如GBK)就会造成大量的内存空间的浪费。在java平台,虚拟机的内存是有限的。java平台采用的unicode字符集更要尽可能的节省虚拟机内存空间,所以java平台采用Utf-8的编码方式。采用可变长字节编码。对生僻字采用单字节,对经常使用的采用双字节或最多3字节编码。

如下是从网上找到的unicode 与utf-8的转换规则:

0000 - 007F :0xxxxxxx (单字节)

0080 - 07FF :110xxxxx 10xxxxxx (双字节)

0800 - FFFF :1110xxxx 10xxxxxx 10xxxxxx (三字节)
对于unicode码点在0000-007F之间的采用 第一种(单字节)编码方式,对于在0080-07ff之间的unicode值采用第二种(双字节)编码方式,例如汉字的unicode 值是从4E00-9FC3(百度文库至2008年止的数据),基本都在0800-FFFF这个三字节模板范围内,所以使用UTF-8编码方案的话都是存储的3个字节。例如汉字“五”unicode值为4E94,转换为2进制比特流为:0100 1110 10 01 0100 将此比特流变换组合方式 按照 UTF-8的三字节模板填充到里面取代三字节模板里面的X,即构成了11100100 10111010 10010100 即 最后得到的UTF-8编码值为11100100 10111010 10010100 即E4 BA 94。

用程序验证一下:

String s="五";
byte b[]=s.getBytes("utf-8");
for(int i=0;i<b.length;i++){
System.out.println(b[i]);
}

依次打印出来:-28 -70 -108。(计算机均为补码显示)转换为二进制负数的原码

-28 原码为1110 0100

-70 原码为1011 1010

-108原码为1001 0100刚好跟最后得到的UTF-8编码值为11100100 10111010 10010100 一致。

 

3.上面只是以UTF-8为例讲述一下 字符集 编码字符集 编码实现方案 之间的关系。同样GBK 也和UTF-8一样有类似的与unicode转换的规则。因为GBK 是双字节定长编码,所以转换规则为 110XXXXX 10XXXXXX。不同的编码方式采用不同的转换规则,这样构成了所谓的“编码”

抱歉!评论已关闭.