5

我有一个定义,它构建一个由 UTF-8 编码字符组成的字符串。使用'w+', "utf-8"参数打开输出文件。

但是,当我尝试x.write(string)得到UnicodeEncodeError: 'ascii' codec can't encode character u'\ufeff' in position 1: ordinal not in range(128)

我认为这是因为通常你会做'print(u'something')。但是我需要使用一个变量,并且 u' _ ' 中的引号否定了...

有什么建议么?

编辑:这里的实际代码:

source = codecs.open("actionbreak/" + target + '.csv','r', "utf-8")
outTarget = codecs.open("actionbreak/" + newTarget, 'w+', "utf-8")
x = str(actionT(splitList[0], splitList[1]))
outTarget.write(x)

基本上所有这些都应该做的是为我构建大量看起来类似于这样的字符串:

[日木曜 Deliverables]= CASE WHEN things = 11 THEN C ELSE 0 END

4

3 回答 3

5

你在用codecs.open()吗?Python 2.7 的内置open()不支持特定编码,这意味着您必须手动编码非 ascii 字符串(正如其他人所指出的那样),但codecs.open()确实支持这一点,并且可能比手动编码所有字符串更容易插入。


当您实际使用codecs.open()时,通过添加的代码,并在自己查找一些内容后,我建议尝试使用 encoding 打开输入和/或输出文件"utf-8-sig",这将自动处理 UTF-8 的 BOM(参见http ://docs.python.org/2/library/codecs.html#encodings-and-unicode,靠近该部分的底部)我认为这只对输入文件很重要,但如果这些组合都没有(utf -8-sig/utf-8, utf-8/utf-8-sig, utf-8-sig/utf-8-sig) 工作,那么我相信最有可能的情况是您的输入文件被编码为与 BOM 不同的 Unicode 格式,因为 Python 的默认 UTF-8 编解码器将 BOM 解释为常规字符,因此输入不会有问题,但输出可以。


刚刚注意到这一点,但是...当您使用 时codecs.open(),它需要一个 Unicode 字符串,而不是编码字符串;试试x = unicode(actionT(splitList[0], splitList[1]))

尝试解码 unicode 字符串时也可能发生错误(请参阅http://wiki.python.org/moin/UnicodeEncodeError),但我认为这不应该发生,除非actionT()或者您的列表拆分对 Unicode 有影响导致它们被视为非 Unicode 字符串的字符串。

于 2013-07-10T18:08:11.587 回答
5

在 python 2.x 中有两种类型的字符串:字节字符串和 unicode 字符串。第一个包含字节,最后一个包含 unicode 代码点。很容易确定它是什么类型的字符串 - unicode 字符串以u

# byte string
>>> 'abc'
'abc'

# unicode string:
>>> u'abc абв'
u'abc \u0430\u0431\u0432'

'abc' 字符是相同的,因为它们在 ASCII 范围内。\u0430是一个 unicode 代码点,它超出了 ASCII 范围。“代码点”是 unicode 点的 python 内部表示,它们不能保存到文件中。需要先将它们编码为字节。下面是编码后的 unicode 字符串的样子(当它被编码时,它变成了一个字节字符串):

>>> s = u'abc абв'
>>> s.encode('utf8')
'abc \xd0\xb0\xd0\xb1\xd0\xb2'

现在可以将此编码字符串写入文件:

>>> s = u'abc абв'
>>> with open('text.txt', 'w+') as f:
...     f.write(s.encode('utf8'))

现在,重要的是要记住,我们在写入文件时使用了什么编码。因为要能够读取数据,我们需要对内容进行解码。这里的数据看起来像没有解码:

>>> with open('text.txt', 'r') as f:
...     content = f.read()
>>> content
'abc \xd0\xb0\xd0\xb1\xd0\xb2'

你看,我们得到了编码字节,与 s.encode('utf8') 中的完全相同。要对其进行解码,需要提供编码名称:

>>> content.decode('utf8')
u'abc \u0430\u0431\u0432'

解码后,我们得到了带有 unicode 代码点的 unicode 字符串。

>>> print content.decode('utf8')
abc абв
于 2013-07-10T18:23:45.913 回答
1

xgord 是对的,但为了进一步启迪,值得注意的是究竟是什么\ufeff意思。它被称为 aBOM或 a byte order mark,基本上它是对早期 unicode 的回溯,当时人们无法同意他们希望 unicode 采用哪种方式。\ufeff现在所有 unicode 文档都以 an或 an开头,这\uffef取决于他们决定排列字节的顺序。

如果您在第一个位置的这些字符上遇到错误,您可以确定问题是您没有尝试将其解码为 utf-8,并且文件可能仍然没问题。

于 2013-07-10T18:07:59.970 回答