字符编码浅析

字符编码浅析

最近在linux与windows上面做切换,经常会遇到乱码问题,又联想起很多因为字符解析失败,最后debug出来是因为字符编码的问题后,准备仔细研究这一块奇怪的东东。

我主要是使用汉语,所以与我们息息相关的编码时gb2312、GBK和UTF系列。

GB2312是最早的汉语标准,但是最大的问题是收录的汉字太少,导致许多复杂的函数无法在机器中表示。之后Microsoft使用GB2312未使用的编码空间,拓展了收录的字符数。

但是真正的国家标准是GB18030,它收录了7万多个汉字,目前的国内软件都必须支持这个字符集。

如果在一个页面中存在多种语言,那在我们看来就是一堆乱码!所以unicode出现了,但是unicode又会分成很多字符标准:

utf-16 的实现是每个字符有2 byte来表示,但是这种编码方式没有运用在浏览器中。 在windows中使用宽字符进行表示,也是说下面代码虽然有汉字,但是每个s元素都是2 byte,最后的len也还是4!


wchar_t s[10];
int len=0;
 
wcscpy(s, L“李123”);
len = wcslen(s);

wchar_t 其实是 unsigned short,一个 16-bit,C 语言所有的 strxxx 都有相对应的 wcsxxx,字符串前面加上 L,代表宽字符。

每个字可能是 1~6个bytes (2003年后删减剩下 1~4 个 bytes)

  1. US-ASCII (0 ~ 127) : 1-byte
  2. 部分各国字母: 2-byte (例如希腊字母,西里尔字母…)
  3. 其它常用字 : 3-byte (大部分的汉字)
  4. 极少用字 : 4~6-byte (包含罕见汉字 ,麻将牌…)

也就是说平时的英文数字大概一个字符一个byte,而汉字 3 byte。

上面这幅图表示的是utf8的表示方式[1],我们可以看到电脑在寻找这个字符由几个byte主要是看byte 1,有几个1 就有几个byte。


strlen("李123")

上面的代码使用unicode的话就会返回6!下面来分析下大小端与字符编码的关系:

我们都知道小端就是low byte在前,high byte在后,典型使用这种方式就是x86架构。

所以基于上述知识,我们知道在notepad打开一个文档,有时候会读取BOM!BOM 位于文档的开头位置

所以我们在代码读取文档的时候,要小心BOM的存在,BOM 可以告诉你后续内容的编码方式,有时候必须跳过 BOM,不要把 BOM 当成内容一起处理。

在Linux 中解决代码转换问题:iconv,而一些特定的语言例如python使用 str.encode(‘utf-8′)。

I18N:所有的语言都写在外部txt,方便做本地适配,代码也不用重新编译。

[1] htpt://en.wikipedia.org/wiki/UTF-8