字符编码问题(2)

1. 常见的编码方式

前一篇中讲到了几个不同的编码方式、字节序、BOM。现在简单回顾一下

  • ASCII 英文一个字节

  • ANSI 在中文系统中ANSI一般指GB2312或GBK。GB2312、GBK都属于双字节字符集 (DBCS)

  • GB2312,GBK 中文两个字节,英文一个字节

  • UTF-8 中文三个字节,英文一个字节

  • UCS-2 中文两个字节,英文两个字

  • BOM 字符"ZERO WIDTH NO-BREAK SPACE"称作BOM,它的UTF-8编码是EF BB BF

  • 字节序 多字节编码方式存在Big endian和Little endian的问题

2. 几个问题

  1. GB2312、GBK都属于双字节字符集 (DBCS)。那英文字母等字符到底是由几个字节表示?

Notepad++使用ANSI编码格式创建一个G.txt文件,内容如下:

汉字a

Python读取这个文件,发现长度为5,输出结果如下:

>>> os.path.getsize('G.txt')
5L
>>> g = file('G.txt')
>>> g.read(2)
'\xba\xba'
>>> g.read(2)
'\xd7\xd6'
>>> g.read(2)
'a'

可见,在GB2312/GBK的编码中,数字和字母(也就是说ACSII码所能表示的字符)都编码成一个字节。具体来说是,00–7F范围内是用一个字节进行编码,和ASCII保持一致

2.Notepad++使用UTF-8 无BOM编码格式创建一个G.txt文件,内容仍然是"汉字a”。Python读取这个文件,发现长度为7,输出结果如下:

>>> os.path.getsize('G.txt')
7L
>>> g = file('G.txt')
>>> g.read(3)
'\xe6\xb1\x89'
>>> g.read(3)
'\xe5\xad\x97'
>>> g.read(1)
'a'

符合前面说的"中文三个字节,英文一个字节”

3.BOM是什么? Notepad++使用UTF-8 格式创建一个G.txt文件,内容仍然是"汉字a”。Python读取这个文件,发现长度为10,输出结果如下:

>>> os.path.getsize('G.txt')
10L
>>> g = file('G.txt')
>>> g.read(3)
'\xef\xbb\xbf'
>>> g.read(3)
'\xe6\xb1\x89'
>>> g.read(3)
'\xe5\xad\x97'
>>> g.read(1)
'a'

基本与"UTF-8 无BOM"编码格式相同,不过是文本最前面多出了EF BB BF三个字节。符合前面说的"BOM的UTF-8编码是EF BB BF”

4.多字节编码时需要BOM?什么是字节序
Notepad++分别使用UCS-2 大端格式和 UCS-2 小端格式创建一个G.txt文件,内容仍然是"汉字a”。Python读取这个文件,发现长度为8,输出结果如下:

>>> os.path.getsize('G.txt')
8L
>>> g = file('G.txt')
>>> g.read(2)
'\xfe\xff'
>>> g.read(2)
'lI'
>>> g.read(2)
'[W'
>>> g.read(2)
'\x00a'
>>> g.close()
>>> ...
>>> os.path.getsize('G.txt')
8L
>>> g = file('G.txt')
>>> g.read(2)
'\xff\xfe'
>>> g.read(2)
'Il'
>>> g.read(2)
'W['
>>> g.read(2)
'a\x00'

与上面所说的"UCS-2 中文两个字节,英文两个字"符合。

请不要奇怪为什么"汉字"分别输出成'Il'和'W['。看下面这段代码,你应该很容易明白

>>> s = u'汉字'
>>> s
u'\u6c49\u5b57'
>>> chr(0x6c) + chr(0x49)
'lI'
>>> chr(0x5b) + chr(0x57)
'[W'
>>>

BOM和字节序的输出可参考前一篇

BOM是Byte Order Mark的缩写

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

这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。

你可能感兴趣的:(utf-8,字符编码)