python读取utf-8 with bom格式文件

UTF-8 with bom

UTF-8是一种常见的编码格式,一种是 含BOM,一种是 不含BOM

BOM 即byte order mark,带BOM的UTF-8文件的开头会有 U+FEFF 字符。

在 UTF-8 文件中放置 BOM 主要是 微软 的习惯,但是放在其他系统(linux、unix)上会出现问题。

注意:
不含BOM的UTF-8才是 标准形式 ,UTF-8不需要BOM

测试

使用windows系统的notepad工具新建 文本文件,内容为空,另存选择 UTF-8,如下图:

然后查看该文件属性,其长度为 3字节,而不是0字节,如下图:

说明使用notepad工具保存的UTF-8格式文件,是含有 BOM 的。

但这3个字节 不可显示,所以 看不见

注意:

必须是notepad工具,其他工具保存的utf-8,可能无bom

读取UTF-8 with bom文件

使用windows自带文本编辑器notepad工具新建文本文件,内容如下:

床前明月光
疑是地上霜
举头望明月
低头思故乡

保存为utf-8格式

注意:
使用notepad保存的utf-8,是有bom的

通过文本文件模式读取

代码如下

with open('c:/users/mym/desktop/1.txt','r',encoding='utf-8') as f:
    c=f.read()
    print(c)

打印到控制台中,发现前面有一个空格,如下:

空格就是无法正常显示的字符 U+FEFF

通过debug模式跟踪代码,可查看到该字符,如下图:

红框处就是 U+FEFF

去掉多余的bom

with open('c:/users/mym/desktop/1.txt','r',encoding='utf-8') as f:
    c=f.read()
    d=c[1:]#截取字符串,去掉开头的bom
    print(d)
    print(len(d))

长度为23,debug模式跟踪代码,发现换行符是\n,20个汉字加上3个\n,所以长度是23

注意:
windows平台的换行符是\r\n,占2个字符,在python中以文本文件模式读取,转换成\n了

注意:
上面的程序有bug,如果读取没有bom的utf-8文件,就会缺少第一个字符

支持读取UTF-8 without bom和with bom文件

完善上面的程序,使其可以读取utf-8 with bom和without bom的文件,代码如下

def readutf(file):
    with open(file,'r',encoding='utf-8') as f:
        data=f.read()
        if data[0:1]=='\ufeff':
            data=data[1:]
        return data

content=readutf('c:/users/mym/desktop/6-1.txt')
print(content)

通过二进制模式读取

with open('c:/users/mym/desktop/1.txt','rb') as f:
    c=f.read()
    print(c)

通过debug模式跟踪代码,可查看到bom的3个字节,如下图:

去掉多余的bom

with open('c:/users/mym/desktop/1.txt','rb') as f:
    b=f.read()
    c=b[3:].decode('UTF-8')#将二进制解码为字符串
    print(c)
    print(len(c))

长度为26,debug模式跟踪代码,发现换行符是\r\n(windows平台的换行方式,占2个字符),20个汉字加上3个\r\n,所以长度是26

注意:
上面的程序有bug,如果读取没有bom的utf-8文件,就会缺少第一个字符

注意:
decode()方法参见链接:
http://www.malaoshi.top/show_1EF2Pg2sje3N.html

支持读取UTF-8 without bom和with bom文件

完善上面的程序,使其可以读取utf-8 with bom和without bom的文件,代码如下

def readutf(file):
    with open(file,'rb') as f:
        data=f.read()
        if data[0:3]==b'\xef\xbb\xbf':
            data=data[3:]
        return data.decode('UTF-8')

content=readutf('c:/users/mym/desktop/6-1.txt')
print(content)

注意:
在判断b'\xef\xbb\xbf'时,可以使用codecs模块的BOM_UTF8属性,见下面代码:

import codecs
print(codecs.BOM_UTF8)

其结果就是:

b'\xef\xbb\xbf'

将上面的程序改动如下:

import codecs
f=open('c:/users/mym/desktop/1.txt','rb')
data=f.read()
if data[:3]==codecs.BOM_UTF8:
    data=data[3:]
print(data.decode('utf-8'))

感谢下面链接
https://blog.csdn.net/legendaryhsl/article/details/78794121


原文出处:/show_1EF2LSjQUHxw.html