用Python理清编码问题:BOM、换行符和编码原则
BOM
es = 'A'
codes = ['utf-32','utf-16']
print([es.encode(code) for code in codes])
[b'\xff\xfe\x00\x00A\x00\x00\x00', b'\xff\xfeA\x00']
,字节序列开头的\xff\xfe就是BOM,有时候他可能是\xfe\xff的形式,这说明文本是大字节序。0xFEFF的UTF-8编码是0x\ef0x\bb0x\bf。Windows记事本中的BOM
# 文件内容都是:abAB巩★☆,但另存为时选择的编码格式不同。
fs = ['ansi.txt','unicode.txt','unicode big endian.txt','utf-8.txt']
for f in fs:
with open(f,'rb') as f_:
print(f_.readline())
b'abAB\xb9\xae\xa1\xef\xa1\xee'
b'\xff\xfea\x00b\x00A\x00B\x00\xe9\x5d\x05\x26\x06\x26'
b'\xfe\xff\x00a\x00b\x00A\x00B\x5d\xe9\x26\x05\x26\x06'
b'\xef\xbb\xbfabAB\xe5\xb7\xa9\xe2\x98\x85\xe2\x98\x86'
ANSI实际采用的是GB系列编码。 Unicode.txt和unicode big endian.txt存储编码是UTF-16。更具体的,根据BOM信息,可知unicode.txt实际格式是UTF-16LE,而unicode big endian.txt实际格式是UTF-16BE。 UTF-8是带有BOM头的UTF-8存储格式。
其它编辑器的BOM
vim设置中,查询BOM
:set bomb?
,取消BOM::set nobomb
,设置BOM:set bomb
Windows的ANSI和代码页
chcp
可见。比如简体中文的操作系统会返回活动代码页;936
,这就是CP936,也就是GBK编码规范。代码页也是指向具体编码的“指针”。^M
和所有行挤成一行的问题。换行符问题
VIM编辑器使用命令
:% ! xxd
转换位十六进制显示;使用命令:% ! xxd -r
转换为文本显示。
Windows系统借鉴这两个字符,使用回车和换行表示一行完成,另起一行。 Unix系统仅仅使用了换行符。 Unix系统打开Windows系统的文件时,由于多了回车符号,常看到行末尾出现奇怪的 ^M
符号,这是Unix解析\r产生的。Windows系统里打开Unix系统文件时,由于少了回车符,所有行挤在一起,变成一行。 Mac系统使用回车\r表示换行。
Python编程中编码问题
建议使用UTF-8
decode和encode用法
Unicode码位转字节序列时用encode 字节序列转为Unicode时用decode
str = 'abAB巩' #Unicode码位
gbk_seq = str.encode('gbk') #Unicode码位转GBK字节序列
str2 = gbk_seq.decode('gbk') #GBK字节序列转Unicode码位
utf_seq= str2.encode('utf-8') #Unicode码位转UTF-8字节序列
print(str,str2,gbk_seq,utf_seq)
Python2字面量实际是带有编码格式的字节序列。
三明治原则
with open('ansi.txt','r',encoding='gbk')as f,open('u8.txt','w',encoding='utf-8') as f2:
s = f.readline()
s = s[::-1]
f2.write(s)
不要使用python2
s = 'abAB巩’
,是一个字节序列,它的具体值根据采用的编码(GBK,UTF-8)而不同。u = u'abAB巩'
表示的是Unicode码位。另外Python2中的编码类型声明# -*- coding:utf-8
声明的是程序中常量的编码类型,需要和文本保存编码类型一致。使用chardet推测字节序列的编码
若无法确定字节流的编码,模块chardet可用来推测字节流的编码。
import chardet
chardet.detect(b'\xef\xbb\xbfabAB\xe5\xb7\xa9\xe2\x98\x85\xe2\x98\x86')
{'encoding':'utf-8',...}
,指出了最可能的编码及其可信度。总结
为了自标记文件编码,引入了BOM标签。我们分析了BOM在记事本中的表现,了解了BOM并不是强制要求。
了解了BOM、换行符导致的Linux和Windows之间的许多问题。
学习了Python中编程的三明治原则;读写文件时,显式指明文件编码。
本系列总结
从ASCII的简单,但不支持其他国家文字。
到扩展ASCII支持其他国文字,但产生乱码。
再到MBCS多字节编码可以支持汉语这种很多字符的语言,但由于太多语言编码导致各自为战互不兼容。
Unicode统一了世界各语言字符。Unicode几种编码形式中;
UTF-32简单,但浪费严重。
UTF-16使用两个字节为单位存储,节省了空间。
UTF-8使用一个字节直接存储,是效率、空间的平衡。
为了自标记文件编码,引入了BOM标签。我们分析了BOM在记事本中的表现,了解了BOM并不是强制要求。
了解了BOM、换行符导致的Linux和Windows之间的许多问题。
学习了Python中编程的三明治原则;读写文件时,显式指明文件编码。
本文代码
https://gitee.com/gongqingkui/codes/0qku9tc6az3j2dvoy5s8w39
作者:巩庆奎,大奎,对计算机、电子信息工程感兴趣。gongqingkui at 126.com
赞 赏 作 者
更多阅读
特别推荐
点击下方阅读原文加入社区会员
评论