字符编码解码总结

字符编码解码总结

前言

字符编码解码这个问题一直困扰着诸多的程序开发者,可能也查阅过不少资料,可在实际编码工作中对于一些问题还是一知半解。
例如笔者在最初学习时,知道编码是将字符转换为二进制码,但似乎由觉得Unicode也是码,可资料又说在某些语言如Python中,Str是字符串,也是Unicode,可字符串怎么又可能是’码‘呢?这些疑问一直迷惑着笔者。好在最后经过一些学习和了解,整理了一些内容,将这些问题解释清楚了,以供参考。

现代编码模型

为了全面地了解字符编码与解码,先学习了解现代编码模型是十分必要的。该模型脱离具体编程语言,了解了它才能了解字符编码的核心。

现代编码模型自底向上分为五个层次:

  • 抽象字符表 ACR (Abstract Character Repertoire)
  • 编码字符集 CCS (Coded Character Set)
  • 字符编码表 CEF (Character Encoding Form)
  • 字符编码方案 CES (Character Encoding Schema)
  • 传输编码语法 TES (Transfer Encoding Syntax)

抽象字符表ACR

抽象字符表(ACR)也称为抽象字符集,或字符集。表示由若干字符组成的集合,该集合是无序的。这些字符包括英文字母、中文汉字等。更为具体地说,抽象字符 英文字母A同时属于US-ASCII, UCS, GBK这三个字符集。
抽象字符 中文文字不属于US-ASCII,属于GBK字符集,也属于UCS字符集。

抽象字符集也是有开放与封闭之分的。开放的字符集指还会不断新增字符的字符集,封闭字符集是指不会新增字符的字符集。

编码字符集CCS

为了更好的描述,操作字符,我们可以为抽象字符集中的每个字符关联一个数字编号,这个数字编号称之为码位(Code Point)。通常根据习惯,我们为字符分配的码位通常都是非负整数,习惯上用十六进制表示。且一个编码字符集中字符与码位的映射是一一映射
编码字符集就是一个每个所属字符都分配了码位的抽象字符集。编码字符集(CCS)也经常简单叫做字符集(Character Set)。
对于同一个字符,使用抽象字符集与编码字符集描述它,有着如下不同:

  • ASCII(抽象)字符集中的那个代表什么都没有的通常表示为NULL的抽象字符
  • ASCII(编码)字符集中的0号字符

最常见的编码字符集就是统一字符集 UCS,通常说的“Unicode字符集”指的就是它。但是,有时“Unicode”这个词本身指的是一系列用于计算机表示所有语言字符的标准。

字符编码表CEF

已经有了编码字符集,且这个字符集中的每个字符都有一个非负整数码位与之一一对应。是否解决所有问题了呢?答案是否定的。因为UCS是一个开放字符集,未来可能有更多的符号加入到这个字符集中来。也就是说UCS需要的码位,理论上是无限的。但计算机整形能表示的整数范围是有限的。一对有限与无限的矛盾,必须通过一种方式进行调和。这个解决方案,就是字符编码表(Character Encoding Form)。

字符编码表将码位(Code Point)映射为码元序列(Code Unit Sequences)。

  • 码元
    码元是能用于处理或交换编码文本的最小比特组合。通常计算机处理字符的码元为一字节,即8bit。

在Unicode中,指定了三种标准的字符编码表,UTF-8, UTF-16, UTF-32。分别将Unicode标量值映射为比特数为8、16、32的码元的序列。

需要注意一点的是,CEF将码位映射为码元序列。这个映射必须是一一映射(双射)。
因为当使用CEF进行编码(Encode)时,是将码位映射为码元序列。
而当使用CEF进行解码(Decode)时,是将码元序列还原为码位。

知道了字符编码表CEF是什么还不够,我们还需要知道它是怎么做的。即:如何将一个无限大的整数,一一映射为指定字宽的码元序列。这个问题可以通过变长编码来解决:无论是UTF-8还是UTF-16,本质思想都是通过预留标记位来指示码元序列的长度,从而实现变长编码。

这里的码元序列,是否就是我们编码之后得到的二进制序列?答案是否定的。为了了解它,还需要了解字符编码方案。

字符编码方案

简单说,字符编码方案 CES 等于 字符编码表CEF 加上字节序列化的方案。也就是说,通过CEF得到码元序列,还需要对其字节排序,得到的就是最后的编码结果。

对于一个字符按照UTF16拆成了若干个码元组成的码元序列,因为每个码元都是一个unsigned short,实际上是两个字节。因此将码元序列化为字节序列的时候,就会遇到一些问题。

  • 大小端序问题:每个码元究竟是高位字节在前还是低位字节在前呢?
  • 字节序标记问题:另一个程序如何知道当文本是什么端序的呢?这些都是CEF需要操心的问题。

字节序标记BOM (Byte Order Mark),则是放置于编码字节序列开始处的一段特殊字节序列,用于表示文本序列的大小端序。

对于这两个问题的不同答案,在3种CEF:UTF-8,UTF-16,UTF-32上。
Unicode实际上定义了 7种 字符编码方案CES:

  • UTF-8
  • UTF-16LE
  • UTF-16BE
  • UTF-16
  • UTF-32LE
  • UTF-32BE
  • UTF-32

其中UTF-8因为已经采用字节作为码元了,所以实际上不存在字节序的问题。其他两种CES嘛,都有一个大端版本一个小端版本,还有一个随机应变大小端带BOM的版本。

这里也出现一个问题,历史上字符编码方案(Character Encoding Schema)曾经就是指UTF(Unicode Transformation Formats)。所以UTF-X到底是属于字符编码方案CES还是属于字符编码表CEF是一个模棱两可的问题。UTF-X可以同时指代字符编码表CEF或者字符编码方案CES。

简单的说,字符编码表CEF和字符编码方案CES区别如下:

  • 字符编码表CEF将码位映射为码元序列
    CCS ---CEF--> Code Unit Sequence
  • 字符编码方案CES将码位序列化为字节流。
    CCS ---CES--> Byte Sequence

总结:
我们通常所说的动词编码(Encode)就是指使用CES,将CCS中字符组成的字符串转变为字节序列。
而解码(Decode)就是反过来,将 编码字节序列 通过CES的一一映射还原为CCS中字符的序列。

对于一些字符集的编码方案太简单,以至于CCS,CEF,CES三层直接合一了。例如US-ASCII的CES,因为ASCII就128个字符,只要直接把其码位转换成(char),就完成了编码。如此简单的编码,直接让CCS,CEF,CES三层合一。很多其他的字符集也与之类似。

传输编码语法(Transfer Encoding Syntax)

通过CES,我们已经可以将一个字符表示为一个字节序列。但是有时候,字节序列表示还不够。比如在HTTP协议中,在URL里,一些字符是不允许出现的。这时候就需要再次对字节流进行编码。著名的Base64编码,就是把字节流映射成了一个由64个安全字符组成字符集所表示的字符流。从而使字节流能够安全地在Web中传输。

Python 3 中的字符编码解码

转换关系

  • str ---encode--> byte
  • str <--decode--- byte

在str中,没有decode方法,在bytes中,没有encode方法。

>>> u'好'
'好'
>>> '好'
'好'
>>> u'\u597d'
'好'
>>> u'\u597d'.encode('utf-8')
b'\xe5\xa5\xbd'

前缀带u的,和不带u的字符串是等价的,同时,'597d'表示’好‘的CCS字符集’码位‘。对于'\u597d'在Python中似乎与字符串’好‘等价

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容