换行符的ascii码值是_ascii码是7位字符编码_ascii码是什么的缩写

BOM

自标记文件编码,UTF编码系列采用的是BOM技术,就是使用一个特殊字符(zero width no-break space),一个Unicode没用到的码位,其值为0XFEFF,放置在文件开头,当编辑器读的时候,看到这个BOM就知道文件采用的什么编码。

es = 'A'
codes = ['utf-32','utf-16']
print([es.encode(code) for code in codes])

其输出[b’xffxfex00x00Ax00x00x00′, b’xffxfeAx00′],字节序列开头的xffxfe就是BOM,有时候他可能是xfexff的形式,这说明文本是大字节序。0xFEFF的UTF-8编码是0xef0xbb0xbf。

当我们使用UTF-16LE或者BE编码时,其输出不带BOM头。这是因为程序认为我们既然明确指定了带大小端的编码,说明我们知道并掌握自己怎么使用字节序列。

Windows记事本中的BOM

BOM技术在Windows的记事本中比较常见,新建一个文本文件,写入相同内容,然后另存为记事本支持的四种格式:ANSI、Unicode、Unicode big endian、utf-8,查看其二进制形式,可见其BOM字段和相应编码的字节序列。Python打开文件时的’b’选项,使用二进制模式读取。

# 文件内容都是: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'abABxb9xaexa1xefxa1xee'
b'xffxfeax00bx00Ax00Bx00xe9x5dx05x26x06x26'
b'xfexffx00ax00bx00Ax00Bx5dxe9x26x05x26x06'
b'xefxbbxbfabABxe5xb7xa9xe2x98x85xe2x98x86'

从字符巩可以看出

其它编辑器的BOM

记事本使用BOM作文本编码信息的自标记,但是这并不是对编辑器的强制要求,也就是可带可不带,比如Linux下VIM编辑器,就不带BOM信息,这也是跨操作系统、编辑器编辑时,经常遇到问题的地方。

vim设置中,查询BOM:set bomb?,取消BOM::set nobomb,设置BOM:set bomb

上文中的ANSI为啥是GB系列编码呢?

Windows的ANSI和代码页

至于ANSI格式为什么用GB系编码形式,需要多说一句。ANSI是美国国家标准协会,各国(非拉丁语系国家)指定自身文字编码,得到ANSI的认可之后使用。所以各个国家的ANSI实际指代编码各不相同换行符的ascii码值是,比如中国是GB2312,日本JIT,台湾地区Big5。ANSI实际是指向具体编码的“指针”。

相较于,Windows记事本用ANSI来指代本地区的编码;Windows系统用代码页指代本系统编码换行符的ascii码值是,但这两个概念可视为一个概念。代码页或ANSI从命令行窗口输入chcp可见。比如简体中文的操作系统会返回活动代码页;936,这就是CP936,也就是GBK编码规范。代码页也是指向具体编码的“指针”。

在记事本选择ANSI格式,实际是选择当前系统的活动代码页指代的具体编码,本例中选记事本ANSI,就是选代码页936,代码页CP936就指向GBK编码。

在Unix系统和Windows系统间切换时,经常出现文本出现^M和所有行挤成一行的问题。

换行符问题

Window下,UE编辑器或者vim的十六进制打开文件时,可看到文件的最后有0x0d0a这两个字节。这分别是Windows中的换行(0x0a或n)和回车(0x0d或r)的ASCII码。

VIM编辑器使用命令:% ! xxd转换位十六进制显示;使用命令:% ! xxd -r转换为文本显示。

这要从机械打字机说起,机械打字机打印完一整行之后,需要手动将“车”拉回到左侧,在回车的过程中,打字机自动完成了换行的操作,就可以继续打印第二行。

Mac系统使用回车r表示换行。

Python编程中编码问题

以上,我们理清了字符编码的发展脉络,知道了BOM以及不同操作系统、编辑器对BOM的应用。在Python编程中,我们如何处理编码问题呢?有以下几个注意事项:

建议使用UTF-8

为了国际交流的便捷,Python使用UTF-8作为默认编码格式,在日常网页编程,数据库默认编码,以及文本存储时都建议使用UTF-8。

decode和encode用法

什么时候encode,什么时候decode呢?需要记住一个原则:Python3字符串是Unicode码位,也就是说所有Python字面量实际是Unicode码位整数。所有转换都要以Unicode码位为中间体:

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字面量实际是带有编码格式的字节序列。

三明治原则

三明治原则是在读写文件时,一定显式指定文件编码,确保Python程序中只处理Unicode码位,而不涉及字节序列。只有在输入和输出时,文件才转换为相应编码下的字节流。这种两端有具体编码,内里只有Unicode的处理方式,像两片面包夹着食材,所以称为三明治原则。

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)

以上代码,s字符串相关的处理都是Unicode码位。只有输入和输出时,才指定了相应的编码GBK和UTF-8。

不要使用python2

不要使用python2!Python2中的Str类型,既是字符串,又是字节序列类型,特别复杂。非有特殊要求,建议不要使用。以下内容,足以一窥Python2的复杂:

Python2中,s = ‘abAB巩’,是一个字节序列,它的具体值根据采用的编码(GBK,UTF-8)而不同。u = u’abAB巩’表示的是Unicode码位。另外Python2中的编码类型声明# -*- coding:utf-8声明的是程序中常量的编码类型,需要和文本保存编码类型一致。

使用chardet推测字节序列的编码

若无法确定字节流的编码,模块chardet可用来推测字节流的编码。

import chardet
chardet.detect(b'xefxbbxbfabABxe5xb7xa9xe2x98x85xe2x98x86')

返回是一个字典{‘encoding’:’utf-8′,…},指出了最可能的编码及其可信度。

总结本系列总结

为了自标记文件编码,引入了BOM标签。我们分析了BOM在记事本中的表现,了解了BOM并不是强制要求。

了解了BOM、换行符导致的Linux和Windows之间的许多问题。

学习了Python中编程的三明治原则;读写文件时,显式指明文件编码。

人类交流因语言文字不同,造成很大困扰,无数IT从业人员也遇到各种乱码折磨,不认真攻克编码问题,他就会时不时跳出来。需要我们认清编码是发展和优化平衡的结果,包含了一系列优化、例外和兼容。

本文代码

作者:巩庆奎,大奎,对计算机、电子信息工程感兴趣。gongqingkui at 126.com

赞 赏 作 者

发表回复

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