前言

此前遇到过UTF8格式的文件有无BOM的导致的问题,最近在做自动化测试,读写配置文件时又遇到类似的问题,和此前一样,又是折腾了挺久之后,通过工具比较才知道原因。

两次在一个问题上面栽更头,就在想有没有一个一劳永逸的方法避免这个问题,或者能做到检测,不用到最后借助Beyond Compare进行16进制比较。

之前的博客中UTF8格式的文件有无BOM做了比较详细的说明,有兴趣的可以看看:

UTF-8文件的Unicode签名BOM(Byte Order Mark)问题记录(EF BB BF)

Python codecs

此前很少使用codecs,查阅了相关资料知道这个是一个好东西。

比如说当我们有数据要保存的时候,大多数时候会选择保存到TXT中,当然数据量大的时候,保存到数据库还是比较方便,然后在网络传输的时候需要序列号、json化。

而我们操作txt平常用得最多的就是open内置函数,或者file这个工厂函数,两者效果基本一样。

但是我们用open方法打开文件有时候会有一些问题,因为open打开文件只能写入str类型,而不会管字符串是什么编码方式。

例如这样是可以的,示例:

>>> fr = open('test.txt','a')
>>> line1 = "我爱祖国"
>>> fr.write(line1)

但是有时候我们爬虫或者其他方式得到一些数据写入文件时会有编码不统一的问题,此时写入open方式打开的文件就有问题了。示例:

>>> line2 = u'我爱祖国'
>>> fr.write(line2) Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
fr.write(line2)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-11: ordinal not in range(128)

怎么办?我们可以将上面的line2编码成str类型。

操作步骤:先把原数据decode为unicode再encode为str,太麻烦了。。。

input文件(gbk, utf-8...)   ----decode----->   unicode  -------encode------> output文件(gbk, utf-8...)

其实Python提供了更简单的做法,那就是今天的主角codecs.open,示例:

>>> import codecs
>>> fw = codecs.open('test1.txt','a','utf-8')
>>> fw.write(line2)
>>>

没有报错,写入成功!

其实Python对多国语言的处理是支持的很好的,它可以处理当下任意编码的字符。

有一点需要清楚的是,当python要做编码转换的时候,会借助于内部的编码,转换过程是这样的:

原有编码 -> 内部编码 -> 目的编码

而codecs提供的方法可以指定一个编码打开文件,使用这个方法打开的文件读取返回的将是unicode。写入时,如果参数是unicode,则使用open()时指定的编码进行编码后写入;如果是str,则先根据源代码文件声明的字符编码,解码成unicode后再进行前述 操作。相对内置的open()来说,这个方法不容易在编码上出现问题。所以,推荐大家在文件读写的时候使用codecs

检测及消除BOM

然后继续我们今天的另外一个主题,怎么样消除UTF-8文件中的名BOM(Byte Order Mark),十六进制编码(EF BB BF),博主的方法有些取巧但是也比较高效,主要用到了codecs的函数BOM_UTF8,如果发现BOM_UTF8,则直接改写文件内容。

示例代码:

import codecs

with open(config_path) as source_file:
data = source_file.read() # remove BOM
if data[:3] == codecs.BOM_UTF8: # 判断是否为带BOM文件
data = data[3:]
with codecs.open(config_path) as dest_file:
dest_file.write(data)

相关读写模式

codecs有如下的读写模式,和open用法基本一致。

模式 描述
r 仅读,待打开的文件必须存在
w 仅写,若文件已存在,内容将先被清空
a 仅写,若文件已存在,内容不会清空
r+ 读写,待打开的文件必须存在
w+ 读写,若文件已存在,内容将先被清空
a+ 读写,若文件已存在,内容不会清空
rb 仅读,二进制,待打开的文件必须存在
wb 仅写,二进制,若文件已存在,内容将先被清空
ab 仅写,二进制,若文件已存在,内容不会清空
r+b 读写,二进制,待打开的文件必须存在
w+b 读写,二进制,若文件已存在,内容将先被清空
a+b 读写,二进制,若文件已存在,内容不会清空

相关资料:

https://www.cnblogs.com/buptldf/p/4805879.html

https://blog.csdn.net/chenyxh2005/article/details/72465758

https://blog.csdn.net/zhaoweikid/article/details/1642015

【Python】使用codecs模块进行文件操作及消除文件中的BOM的更多相关文章

  1. 孤荷凌寒自学python第三十五天python的文件操作之针对文件操作的os模块的相关内容

     孤荷凌寒自学python第三十五天python的文件操作之针对文件操作的os模块的相关内容 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.打开文件后,要务必记得关闭,所以一般的写法应当 ...

  2. JAVASE02-Unit06: 文件操作——File 、 文件操作—— RandomAccessFile

    Unit06: 文件操作--File . 文件操作-- RandomAccessFile java.io.FileFile的每一个实例是用来表示文件系统中的一个文件或目录 package day06; ...

  3. Unix无缓冲文件操作函数、文件信息查询

    问题描述:         Unix无缓冲文件操作函数.文件信息查询 问题解决:        struct stat 结构体信息: 具体代码: 具体源文件:

  4. 重新想象 Windows 8 Store Apps (24) - 文件系统: Application Data 中的文件操作, Package 中的文件操作, 可移动存储中的文件操作

    原文:重新想象 Windows 8 Store Apps (24) - 文件系统: Application Data 中的文件操作, Package 中的文件操作, 可移动存储中的文件操作 [源码下载 ...

  5. JAVA文件操作类和文件夹的操作代码示例

    JAVA文件操作类和文件夹的操作代码实例,包括读取文本文件内容, 新建目录,多级目录创建,新建文件,有编码方式的文件创建, 删除文件,删除文件夹,删除指定文件夹下所有文件, 复制单个文件,复制整个文件 ...

  6. java文件操作(普通文件以及配置文件的读写操作)

    转自:java文件操作(普通文件以及配置文件的读写操作) 读取普通文件 : /** * xiangqiao123欢迎你 如果对代码有疑问可以加qq群咨询:151648295 * * 读取MyFile文 ...

  7. Python:文件操作总结1——文件基本操作

    一.文件的操作流程 1.打开文件,得到文件句柄并赋值给一个变量 2.通过句柄对文件进行操作 3.关闭文件 二.文件的打开与关闭 A.文件的打开——open函数 语法:open(file[,mode[, ...

  8. 文件操作 - 三元运算/chardet/文件操作r w/文件的操作方法

    Alex:读书可以改变一个人的气质读书:豆瓣: 1年读20本 你的问题:想法太多,读书太少 书:追风筝的人,白鹿原  电影:阿甘正传 辛德勒名单---------------------------- ...

  9. day8 八、文件操作模式、文件的复制与文件游标操作

    一.文件操作 1.wr模式结合 ① w = open('1.txt', 'w', encoding='utf-8') # w:没有文件新建文件,有文件就清空文件 w.write('000\n') w. ...

随机推荐

  1. 树链剖分-点的分治(链的点的个数为k的点对数)

    hdu4760 Cube number on a tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65535/65535 ...

  2. log4j 设置将生成的日志进行gz压缩并删除过期日志

    1.准备jar  :log4j-1.2.17.jar,commons-logging-1.2.jar,这2个就可以了,其他关于日志的jar包就不要加进来了,在优先级上会有冲突. 2.定义一个类,继承R ...

  3. Day19 客户关系系统实战

    day19 今日内容 Service事务 客户关系管理系统     Service事务 在Service中使用ThreadLocal来完成事务,为将来学习Spring事务打基础! 1 DAO中的事务 ...

  4. 【Python】自动化测试框架-共通方法汇总

    1.滚动滚动条(有的时候页面元素element取得对但是并没有回显正确的数据,可能是因为页面第一次加载很慢,所以页面可能做了滚动到哪里就加载到哪里的效果,此刻我们就需要用到滚动条自动滚动这段代码让页面 ...

  5. 【Loadrunner】性能测试:通过服务器日志获取性能需求

    性能测试:通过服务器日志获取性能需求          接触过性能测试的童鞋都知道,想要做好一个项目的性能测试,性能需求的获取至关重要~!如果公司有做过性能测试还好,大家可以拿之前的性能测试数据作为参 ...

  6. Java压缩多个文件并导出

    controller层: /** * 打包压缩下载文件 */ @RequestMapping(value = "/downLoadZipFile") public void dow ...

  7. controller中两个方法之间共享一个变量LinkedHashMap

    1:引用传递,创建一个变量,给两个线程都传递进去. 2:静态修饰 static  通过该修饰符说明,该变量只有一份,  所有线程共用一份. 例如下面的htmlidMap通过static变量修饰, up ...

  8. (转)在GitHub多个帐号上添加SSH公钥

    GitHub后台可以添加多个SSH Keys,但是同一个SSH Keys只能在添加在一个帐号上(添加时提示“Key is already in use”).理由很容易想到,SSH公钥使用时相当于用户名 ...

  9. JOJ1202。重新操刀ACM,一天一练!做个简单的题目温习。

    http://ac.jobdu.com/problem.php?pid=1202 题目描述: 对输入的n个数进行排序并输出. 输入: 输入的第一行包括一个整数n(1<=n<=100).   ...

  10. VS Code 终端窗口无法输入命令的解决方案

    问题 今天打开vs code,打开终端窗口,发现不能输入命令了 解决方法 邮件桌面 vscode的快捷键,打开“兼容性”标签,勾选"以管理员身份运行此程序" 结果 修改之后重启vs ...