去年在写一个批量读取文件夹下的指定文件类型的所有文件中遇到了一个小错误,今天终于把他干掉了,小小的成就感,记录一下
错误:
1 Traceback (most recent call last): 2 File "<pyshell#84>", line 1, in <module> 3 open(path, encoding='gbk', mode='r').read() 4 UnicodeDecodeError: 'gbk' codec can't decode byte 0x88 in position 38: illegal multibyte sequence
解决办法:
#! python3 # chapter08-test03.py - 打开文件夹中所有的.txt文件,查找匹配用户提供的正则表达式的所有行 # 结果打印在屏幕上 import os,re import chardet #定义获取文件编码的函数 def get_encoding(file): with open(file,'rb') as f: return chardet.detect(f.read())['encoding'] path=os.path.join('F:\便签') fileNameList=os.listdir(path) #listdir()返回一个包含路径path下所有文件名称的列表 for objFile in fileNameList: fileType=os.path.splitext(os.path.join(path,objFile)) #splitext()会返回路径名和扩展名的元组 if fileType[1]=='.txt': correctFileName=os.path.join(path,objFile)#拼接出来文件的完整地址 encoding=get_encoding(correctFileName) #这里是关键点 searchObjFile=open(correctFileName,encoding=encoding,errors='ignore') print('*'*20+str(correctFileName)+'*'*20) #重复打印的快捷方式是这样的 print(searchObjFile.read()) searchObjFile.close()
详细过程:
首先错误是有python3的默认编码与要打开文件的编码不同导致的
我搜到的第一个解决办法是将默认编码改成‘gbk’
searchObjFile=open(correctFileName,encoding=‘gbk’,errors='ignore')
结果无效
第二次解决办法的思想是获取每个文件的编码类型,用相应的编码去创建文件对象,这样动态的调用 open() ,这样做需要
1)获取文件编码
#定义获取文件编码的函数 def get_encoding(file): with open(file,'rb') as f: return chardet.detect(f.read())['encoding']
open() 中的‘rb’代表用二进制打开一个文件用于只读, chardet.detect(data) 用于检测data的编码类型,至于后面的 ['encoding'] 我也不知道
2)然后就是在每次调用 open() 之前获取文件编码,然后调用时传入即:
searchObjFile=open(correctFileName,encoding=encoding,errors='ignore')
可以通过设置 errors 来控制出现错误时的策略
默认的参数就是strict,代表遇到非法字符时抛出异常; 如果设置为ignore,则会忽略非法字符; 如果设置为replace,则会用?取代非法字符; 如果设置为xmlcharrefreplace,则使用XML的字符引用
这个方法有效 感谢作者!>>>原文链接