关于字符编码
Posted
以下内容纯个人理解,如有遗漏/错误等我反应过来再补充吧~
(感觉还是用类似Q&A的方式来写写比较好)
######什么是字符?
在计算机里面,无意义的二进制0和1(如果不知道的话,继续看下去也没什么意义了。。。),按照特定的长度可以表示一个数值(例如二进制的1000
表示十进制的8
);对于不同的数值,如果有一个table来映射(有没有密码本的赶脚),那不同的数值就可以表示特定的含义 — 字符。
例如,二进制里面的01000001
:
- 十进制(也理解成表的话,只是“映射”方式更简单)就是
65
- 在
ASCII
表里,对应的是英文大写字母A
你看,同一个数值,通过不同的table,就有了不同的含义(小马过河的即视感。。。)。
######什么是字符编码?
很显然,ASCII
这个表能表示的含义太少了(只有128个,而且其中还有33个不能显示的字符),尽管用来表示英文(A-Z
+ a-z
+ 一些常用符号)是足够了,但你让其他语言怎么看?
所以不同的国家,就有了各自的一张Table;这些Tables,就统称为ANSI
编码。所以一般说ANSI
编码,不是单指简体中文的GB2312
或者日文的JIS
,而是指这个合集,指这种“每个国家都不同但又是各自国家标准的编码表”。
######一个国家一张表?
一个国家一张表,听起来不错,但有个问题在于 —- 这意味着,同一个数值,在不同国家表示的含义就不同了啊啊啊!
例如十六进制的0xD2BB
这样两个字节:
- 在
GB2312
中表示大写数字一
- 在
JIS
中表示メサ
(不好意思我不知道这是啥意思。。。)
所以这就意味着,同一份文档,在不同国家,可能会出现显示内容完全不同的情况(一般情况下是乱码。。)
尤其是在大互联网浪潮下,这意味着,在本国打开一切OK的网页,在国外打开就是一团浆糊了:
(哈哈,其实本站不是ANSI
编码,这里强制使用ANSI
的JIS
以后~ 就呵呵了~ )
######乱码怎么办?
怎么办?两种办法:
-
一种是找一个标准,大家统一使用,也就是目前渐成主流的
Unicode
编码; -
再一种就是自动转换编码,例如你在大天朝,一般是用
GB2312
(简体中文)编码,那么如果想看一篇使用JIS
编码的文章/网页,就需要你使用的阅读器/浏览器做两件事情:- 自动编码识别 – 让阅读器/浏览器知道这篇文章/网页是
JIS
编码的 - 编码转换 – 将
JIS
编码转换成GB2312
编码(当然也可以在阅读器/浏览器内部,直接用JIS
编码来显示)
- 自动编码识别 – 让阅读器/浏览器知道这篇文章/网页是
######什么是Unicode?
更具体的请Wiki。
简单来说,就是把不同的语言,按照特定的顺序,不重复的排列下去。组成一个巨大的“字典”(这也意味着这个字典的页数要够大)。
重点就是不重复
具体的可以看这里[Wiki]
有一点需要注意的是,Unicode
是统称。
UTF-8/UTF-16/UTF-32
等等,都是Unicode
。
UTF-8
就是为了存储和传输方便,缩小版的UTF-16
。
显然的是,它们可以相互转换(不是查表,而是用公式)。
######为什么需要自动编码识别?
因为,很多情况下,目标文档的编码是未知的。
举个例子,这就好像古时候密码破译的场景,同一个密码,用不同的密码本对照破译,有可能会得到完全相反的含义。所以如何正确识别编码,就变得特别重要。
######那文档没有特定“编码识别符”么?
对,没有统一标准(即使是Unicode
)。或者说没有“强制”执行的标准,来约定必须在文档某个位置标注当前文档编码类型的。
这也就意味着 – 自动编码识别必不可少。
######如何自动编码识别?
很多算法,一句话就是“模式识别”。
举个例子,在中文里,一般会有一些出现频率较高的词,如“的、我”等等;不同的语言,常用词也显然是不一样的(当然可能存在特例,中文的“的”和日文的“的”都是高频词且十六进制数值一样(仅举例,显然不一样嘛),但就目前的统计数据而言,大部分高频词都一样的可能性几乎为0),所以算法基本如下:
- 读取文档的一段内容(例如前4096字节),当然也可以全部读取
- 统计这段内容中对不同编码的高频词的命中率
- 命中率最高者即为“猜”到的编码
就是这么简单。
######自动编码识别就这么简单?
是也不是,人脸识别算法也很简单,但想做好,就很难。
同理。
所有“模式识别”算法,都不可避免面对一个识别率的问题。
想要越高的识别率,就意味着越复杂的算法,越精细的参考点,换言之,越多的if...else
自动编码识别也一样。
当采样太少时(例如整个文本就10字节),识别率会降低(降到很低)。
当样本库太多时,误判率会升高。
这就是难点:如何增加可识别的编码,同时提升识别率。
######主流的自动编码识别开源代码有哪些?
jchardet,Mozilla用在Firefox里用的自动编码识别库。
cpdetector,jchardet就基于它。
多年前,在此基础上做了一些优化(最主要的是优化识别率),已整理到Github上 – CharsetDetector
######编码识别完以后如何编码转换?
找一个编码转换库,大声说“请把这段数据,从编码A转换到编码B”。
回答完毕。
其实简单来说,这类似查汉译英字典的过程。
而编码转换,其实就是若干大字典之间互查。
######有哪些编码转换库?
最有名的应该就是ICU(不是急症病房)
其实我这么说是因为我也只用过这个。。。
原因是:Android
原生支持ICU。换言之,Java也好,JNI也好,都可以直接使用ICU的接口来进行编码转换。
基本就这些了,结果我手贱搜到了一篇《字符,字节和编码》 。。。 写的好浅显易懂啊。。。妈蛋。。。匿了。。。