点击上方“智能与算法之路”,选择“星”公众号

资源干货,第一时间送达

这是一本由程序员写给程序员的有趣读物。 所谓乐趣,就是可以轻松理解一些以前不清楚的概念,增长知识,类似于玩RPG游戏的升级。 组织这篇文章的动机有两个问题:

问题一:

使用记事本的“另存为”可以在GBK、.big、UTF-8编码方式之间进行转换。 同样是txt文件,如何识别编码方式?

很早以前就发现big和UTF-8编码的txt文件开头都会多几个字节,分别是FF、FE()、FE、FF(big)、EF、BB、BF(UTF- 8). 但这些标记基于什么标准呢?

问题二:

最近在网上看到一个.c,实现了UTF-32、UTF-16、UTF-8三种编码方式的相互转换。 对于(UCS2)、GBK、UTF-8这些编码方式,我以前就知道。 但这个程序让我有点困惑,我想不出 UTF-16 和 UCS2 之间有什么关系。

经过查阅相关资料,我终于弄清楚了这些问题,也顺便了解了一些细节。 写一篇文章发给有类似问题的朋友。 本文在编写时力求通俗易懂,但要求读者知道什么是字节,什么是十六进制。

0、大且

big 和 CPU 处理多字节数字的不同方式。 例如,“中文”字符的编码是6C49。 那么写入文件时,前面应该写6C,还是前面写49呢? 如果6C写在前面,那就大了。 或者在前面写49,即。

“”一词出自《格列佛游记》。 小人国的内战源于吃鸡蛋时是从大端(Big-)还是小端(-)打碎鸡蛋。 结果发生了六次叛乱,其中一位皇帝丧命,另一位皇帝丧命。 王座。

我们一般将其翻译为“字节顺序”,并称big为“big ”和“ ”。

1.字符编码、内码,顺便介绍一下汉字编码

字符必须经过编码才能由计算机处理。 计算机使用的默认编码是计算机的内码。 早期的计算机使用 7 位 ASCII 编码。 为了处理汉字,程序员设计了简体中文和繁体中文的big5。

(1980)共收录汉字7445个,其中汉字6763个,其他符号682个。 汉字区内码范围高字节为B0-F7,低字节为A1-FE,占用码位为72*94=6768。 其中五个空缺是 D7FA-D7FE。

支持的汉字太少。 1995年汉字扩展规范GBK1.0收录了21886个符号,分为汉字区和图形符号区。 汉字区包含21003个汉字。 2000年标准是取代GBK1.0的正式国家标准。 该标准收录了27484个汉字,以及藏文、蒙古文、维吾尔文等主要少数民族文字。 目前的PC平台必须支持,对于嵌入式产品没有要求。 所以手机和MP3一般都只支持它。

从ASCII、GBK到,这些编码方式都是向后兼容的,即相同的字符在这些方案中总是具有相同的编码,并且以后的标准支持更多的字符。 在这些编码中,可以统一处理英文和中文。 区分中文编码的方法是高字节的最高位不为0。按照程序员的说法,GBK和GBK都属于双字节字符集(DBCS)。

部分中文语言默认内码仍然是GBK,可以通过升级包进行升级。 不过相比GBK多出来的字符对于普通人来说使用起来比较困难。 通常我们还是用GBK来指代中文内码。

以下是更多详细信息:

原文仍然是位置代码。 从位置码到内码,需要分别在高字节和低字节加上A0。

在DBCS中,GB内码的存储格式总是大的,即高位在前。

两个字节的最高位都是1。但是满足这个条件的码点只有128*128=16384个。 因此,GBK和sum的低字节最高位可能不是1。不过,这并不影响DBCS字符流的解析:读取DBCS字符流时,只要有一个字节的高位为1遇到时,接下来的两个字节可以被编码为双字节,无论低字节如何。 什么叫地位高。

2.UCS和UTF

前面提到,从ASCII、GBK到GBK的编码方式都是向后兼容的。 它只兼容ASCII(更准确地说,兼容ISO-8859-1),不兼容GB码。 例如“中文”的代码是6C49,GB代码是BABA。

它也是一种字符编码方法,但它是由国际组织设计的,可以容纳世界各地所有语言的编码方案。 学名是“-Octet Coded Set”,缩写为UCS。 UCS 可以看作是“Set”的缩写。

据维基百科()记载:历史上,曾有两个组织尝试独立设计,国际标准化组织(ISO)和软件制造商协会()。 ISO 制定了 ISO 10646 项目,协会也制定了项目。

1991年左右,双方都认识到世界不需要两种不兼容的字符集。 于是他们开始合并双方的工作,共同创建一个单一的编码列表。 从.0开始,该项目使用与ISO 10646-1相同的字体和字体。

这两个项目仍然存在并独立发布自己的标准。 该协会现在的最新版本是2005年的4.1.0。最新的ISO标准是10646-3:2003。

UCS指定如何使用多个字节来表示各种文本。 如何传输这些代码是由UTF(UCS)规范规定的。 常见的 UTF 规范包括 UTF-8、UTF-7 和 UTF-16。

IETF和RFC以RFC一贯的风格清晰、明快、严谨地描述了UTF-16和UTF-8的编码方法。 我总是忘记 IETF 是 Task Force 的缩写。 但 IETF 维护的 RFC 是上述所有规范的基础。

3.UCS-2、UCS-4、BMP

UCS 有两种格式:UCS-2 和 UCS-4。 顾名思义,UCS-2是用两个字节编码的,UCS-4是用4个字节编码的(实际上只用了31位,而且最高位必须为0)。 让我们来做一些简单的数学游戏:

UCS-2 有 2^16=65536 个代码点,UCS-4 有 2^31= 代码点。

UCS-4按照最高位为0的最高字节分为2^7=128组,每组按照次高字节又分为256个平面。 每个plane按照第三个字节分为256行(rows),每行包含256个cell。 当然,同一行的单元格只是最后一个字节不同,其余都一样。

第 0 组的平面 0 称为基本平面,或 BMP。 也就是说,在UCS-4中,高两个字节为0的码位称为BMP。

UCS-2是通过从UCS-4的BMP中去除两个前导零字节获得的。 在UCS-2的两个字节之前添加两个零字节就得到了UCS-4的BMP。 并且当前的UCS-4规范没有在BMP之外分配任何字符。

4.UTF编码

UTF-8 以 8 位为单位对 UCS 进行编码。 从UCS-2到UTF-8的编码如下:

UCS-2 编码(十六进制)

UTF-8字节流(二进制)

0000-007F

0080-07FF

0800-FFFF

例如,汉字的编码是6C49。 6C49在0800-FFFF之间,因此必须使用3字节模板:xxxx。 将6C49写入二进制为:0110,用该比特流依次替换模板中的x得到:01,即E6 B1 89。

读者可以使用记事本来测试我们的编码是否正确。

UTF-16 以 16 位为单位对 UCS 进行编码。 对于小于UCS码的UCS码,UTF-16编码等于UCS码对应的16位无符号整数。 对于不小于 的 UCS 代码,定义了一种算法。 不过,由于实际使用的UCS2或UCS4的BMP肯定更小,所以目前可以认为UTF-16和UCS-2基本相同。 但UCS-2只是一种编码方案,实际传输时采用UTF-16,所以还得考虑字节顺序的问题。

5.UTF字节顺序和BOM

UTF-8使用字节作为编码单位,没有字节序问题。 UTF-16使用两个字节作为编码单元。 在解释UTF-16文本之前,必须首先了解每个编码单元的字节顺序。 例如收到的“奎”的代码是594E,“B”的代码是4E59。 如果我们收到UTF-16字节流“594E”,这是“Ku”还是“B”?

规范中推荐的标记字节顺序的方法是BOM。 BOM 不是“Bill Of”BOM,而是字节顺序标记。 BOM 是一个有点聪明的想法:

UCS编码中有一个字符叫“ZERO WIDTH NO-BREAK SPACE”,它的编码是FEFF。 FFFE是UCS中不存在的字符,所以在实际传输中不应该出现。 UCS规范建议我们在传输字节流之前传输字符“ZERO WIDTH NO-BREAK SPACE”。

这样,如果接收方收到FEFF,则说明该字节流是Big-; 如果接收到FFFE,则表示该字节流为-。 因此字符“ZERO WIDTH NO-BREAK SPACE”也称为BOM。

UTF-8不需要BOM来指示字节顺序,但可以使用BOM来指示编码方式。 字符“ZERO WIDTH NO-BREAK SPACE”的UTF-8编码为EF BB BF(读者可以使用我们前面介绍的编码方法来验证)。 因此,如果接收方收到以 EF BB BF 开头的字节流,它就知道它是 UTF-8 编码的。

BOM用于标记文本文件的编码方式。

6. 进一步参考资料

本文主要参考资料是“ISO-IEC 10646 的缩写和”()。

我还发现了两条看起来不错的信息,但是因为我已经有了最初问题的答案,所以我没有阅读它们:

“A 到”()

“集合集合和”()

好了,今天的主题就讲到这里吧,不管如何,能帮到你我就很开心了,如果您觉得这篇文章写得不错,欢迎点赞和分享给身边的朋友。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注