附加到结尾时文件中间的python utf-8-sig BOM

时间:2014-04-18 12:39:25

标签: python utf-8 byte-order-mark

我最近注意到,当使用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

这不是一个错误吗?这是不合逻辑的。 任何人都可以向我解释为什么会这样做? 为什么只有当文件不存在并且需要创建时,他们才设法预先添加BOM?

1 个答案:

答案 0 :(得分:8)

不,这不是一个bug;这是完全正常的预期行为。编解码器无法检测已经写入文件的数量;例如,您可以使用它附加到预先创建但的文件。该文件不是新文件,但它也不包含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的原因。

Microsoft产品主要使用UTF-8 BOM来自动检测文件的编码(例如其中一个遗留代码页)。