Python在文件末尾添加内容时,如果出现BOM,则会在文件中间插入BOM。

8

我最近注意到,使用 utf-8-sig 编码向文件追加内容时,Python的行为方式非常不明显。请参见以下内容:

>>> import codecs, os
>>> os.path.isfile('123')
False
>>> codecs.open('123', 'a', encoding='utf-8-sig').write('123\n')
>>> codecs.open('123', 'a', encoding='utf-8-sig').write('123\n')

以下文本将最终保存到文件中:
<BOM>123
<BOM>123

这不是一个bug吗?这样做完全不合逻辑。 有没有人能解释一下为什么要这样做? 为什么他们不能在文件不存在且需要创建时才添加BOM?


2
不,这不是一个错误;那是完全预期的行为。编解码器无法检测到已经写入文件的数量。 - Martijn Pieters
1个回答

10

不,这不是错误;那是完全正常的,预期行为。编解码器无法检测到已经写入文件的数量;例如,你可以使用它来附加到一个预先创建但 的文件。该文件既不是新的,也不含有BOM。

然后还有其他用例,在流或字节字符串上使用编解码器(例如不使用codecs.open())时,不存在要测试的文件,或开发人员希望始终在输出开头强制实施BOM。

只在文件上使用utf-8-sig;每当使用它时,编解码器将始终写出BOM。

如果你正在直接处理文件,则可以自己测试开头;使用utf-8代替,并手动编写BOM,即编码为U+FEFF ZERO WIDTH NO-BREAK SPACE

import io

with io.open(filename, 'a', encoding='utf8') as outfh:
    if outfh.tell() == 0:
        # start of file
        outfh.write(u'\ufeff')

我使用了更新的io.open()代替codecs.open(); io是为Python 3开发的新的I/O框架,在处理编码文件时比codecs更加稳健。

请注意,UTF-8 BOM实际上几乎没有用处。UTF-8没有可变字节顺序,因此只有一个字节顺序标记。另一方面,UTF-16或UTF-32可以用两种不同的字节顺序之一写入,这就是为什么需要BOM的原因。

UTF-8 BOM主要被微软产品用于自动检测文件的编码(例如不是遗留代码页之一)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接