简述字符集和编码的区别

概述

个人认为这两个概念需要被严格区分,由于这两个概念被混淆的过于严重导致很多人无法正确的理解字符集和编码的关系,混淆了概念写程序的时候就容易出错。简单记录一下个人的理解。

概念理解

字符集

字符集表示的是一个字符的集合。

常见的字符集有: GB2312,GB18030,GBK,Unicode 等

编码

编码的概念就是把字符转化成字节字节字符具体存储的表示。

常见的编码方式有: UTF-8,UTF-16,UTF-32,EUC-CN

几个常见的错误

ANSI 不是编码

本质上,在 Windows 中 ANSI 指的是对应当前系统 locale 的遗留(legacy)编码,微软给的一个概念是 Windows code pages。这个模式会根据当前 locale 选定具体的编码,比如简体中文下 locale 是 GBK,日文下可能就是 Shift_JIS。

把自己这些 code page 称作ANSI是 Windows 的臭毛病。在 ASCII 范围内它们应该是和 ASCII 一致的。

ANSI 不是一个具体的字符集,而是对一些多字节字符集类型的字符集的一个总体的称呼。

ASCII 既是字符集又是编码方案

ASCII 标准本身就直接规定了字符和字符编码的方式,所以既是字符集又是编码方案

python 下的 Unicode 与 Str

python2

Python2 中有两种表示字符序列的类型,分别是 str 和 Unicode,它与 Python3 的不同是,str 的实例包含原始的 8 位值,而 Unicode 的实例包含 Unicode 字符

python2 下 str 编码方式由当前编辑环境决定,若当前编辑环境是 GBK,则 str 中的字符编码存储方式即为 GBK。python2 中有一个 Unicode Object 类型,我们可以将 str 转为这种类型,在 python2 下 Unicode Object 使用的编码方式是 UTF-16,即固定 2 个字节来编码。

我们可以通过两种方法来定义 Unicode Object

s1 = u'你好'
s2 = Unicode('你好','gb2312')

其中 s2 中的 gb2312 代表借助 gb2312 编码位反查 Unicode 编码位

我们也可以借助 encode 方法来完成编码操作(Unicode 转到 Bytes)

s1 = u'你好' # u'\u4f60\u597d'
s1_gbk = s1.encode('gbk') # '\xc4\xe3\xba\xc3'
s1_utf8 = s1.encode('utf-8') # '\xe4\xbd\xa0\xe5\xa5\xbd'

借助 decode 方法来完成反查 Unicode 编码位操作(Bytes 转到 Unicode)

s1 = u'你好' # u'\u4f60\u597d'
s1_gbk = s1.encode('gbk') # '\xc4\xe3\xba\xc3'
s1_unicode = s1_gbk.decode('gbk') # u'\u4f60\u597d'

python3

Python3 里有两种表示字符序列的类型,分别是 bytes 和 str,bytes 的实例包含 8 位值,str 的则包含 Unicode 字符。也就是说 Python3 中字符串默认为 Unicode,但是如果在 Python2 中需要使用 Unicode,必须要在字符串的前面加一个 「u」前缀

所以在 Python2 中的 “str” 现在叫做 “bytes”,而 Python2 中的 “unicode” 现在叫做 “str”

s1 = "你好"
s1_utf8 = s1.encode("utf-8") # b'\xe4\xbd\xa0\xe5\xa5\xbd'
s1_utf8 = bytes(s1,"utf-8") # b'\xe4\xbd\xa0\xe5\xa5\xbd'
s1_unicode = s1_utf8.decode("utf-8") # "你好"

实际编程中五个不可忽视的事实

1.程序中所有的输入和输出均为 byte
2.世界上的文本需要比 256 更多的符号来表现
3.你的程序必须处理 byte 和 unicode
4.byte 流中不会包含编码信息
5.指明的编码有可能是错误的

Be the first to reply

发表评论

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

1 × 1 =