关于utf 8:用Python写入UTF-8文件

Write to UTF-8 file in Python

我真的对codecs.open function很困惑。当我这样做的时候:

1
2
3
file = codecs.open("temp","w","utf-8")
file.write(codecs.BOM_UTF8)
file.close()

它给了我错误

UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position
0: ordinal not in range(128)

如果我这样做:

1
2
3
file = open("temp","w")
file.write(codecs.BOM_UTF8)
file.close()

它很好用。

问题是为什么第一种方法失败了?如何插入物料清单?

如果第二种方法是正确的方法,那么使用codecs.open(filename,"w","utf-8")有什么意义?


我认为问题在于codecs.BOM_UTF8是字节字符串,而不是Unicode字符串。我怀疑文件处理程序试图根据"我打算将Unicode作为UTF-8编码文本写入,但您给了我一个字节字符串"来猜测您真正的意思!

尝试直接为字节顺序标记(即unicode u+feff)编写unicode字符串,以便文件将其编码为utf-8:

1
2
3
4
5
import codecs

file = codecs.open("lol","w","utf-8")
file.write(u'\ufeff')
file.close()

(这似乎给出了正确的答案——一个包含字节ef bb bf的文件。)

edit:s.lott建议使用"utf-8-sig"作为编码,这比自己显式地编写BOM要好,但我将把这个答案留在这里,因为它解释了以前发生的问题。


阅读以下内容:http://docs.python.org/library/codecs.html module-encodings.utf_8_sig

这样做

1
2
3
4
with codecs.open("test_output","w","utf-8-sig") as temp:
    temp.write("hi mom
"
)
    temp.write(u"This has ?")

生成的文件是带有预期BOM的UTF-8。


@S-LOTT给出了正确的过程,但是在Unicode问题上进行扩展,Python解释器可以提供更多的见解。

jon skeet对于codecs模块是正确的(不寻常的),它包含字节字符串:

1
2
3
4
5
6
>>> import codecs
>>> codecs.BOM
'\xff\xfe'
>>> codecs.BOM_UTF8
'\xef\xbb\xbf'
>>>

选择另一个NIT,BOM有一个标准的Unicode名称,可以输入为:

1
2
3
4
>>> bom= u"
{ZERO WIDTH NO-BREAK SPACE}"

>>> bom
u'\ufeff'

也可通过unicodedata访问:

1
2
3
4
>>> import unicodedata
>>> unicodedata.lookup('ZERO WIDTH NO-BREAK SPACE')
u'\ufeff'
>>>

我使用file*nix命令将未知字符集文件转换为utf-8文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- encoding: utf-8 -*-

# converting a unknown formatting file in utf-8

import codecs
import commands

file_location ="jumper.sub"
file_encoding = commands.getoutput('file -b --mime-encoding %s' % file_location)

file_stream = codecs.open(file_location, 'r', file_encoding)
file_output = codecs.open(file_location+"b", 'w', 'utf-8')

for l in file_stream:
    file_output.write(l)

file_stream.close()
file_output.close()