如何将utf-8字符('\xe7\x8e\xa9')写入另一个文件为中文字符?

1 投票
3 回答
9303 浏览
提问于 2025-04-18 16:58

我从数据库里拿到了一些字符串,看起来像是 '\xe7\x8e\xa9'

我觉得这是utf-8格式的。我可以用下面的方式把它们打印出来:

print '\xe7\x8e\xa9'
玩

问题是,我需要把它们写入另一个文件中,作为中文字符(比如说“玩”),还要和其他字母数字数据一起写进去。

我试过用 encodedecode,但是没有得到我想要的结果。

这是我尝试过的:

f = open('a','w')
name = u.name #.encode('utf8')  # I commented it to get raw
f.write('\t$$%r$$many_other_data' % name) 
f.close()

当我用vim7.4打开输出文件时:

 `$$u'\u7aef\u5e84\u7684\u9a6c\u6b47\u5c14$$many_other_data'`

3 个回答

1

文件其实是由字节组成的。你不能直接在文件里存储字符。

一种特别常见的编码方式是ASCII。这就像其他各种unicode编码一样。

这些字节如果没有对应的编码来解释它们的含义,单独看是没有意义的(就像文本一样)。

你需要用一个和你写文件时使用的编码相同的编辑器或查看器来打开这个文件。

1

因为你手里有字节数据,所以你需要知道它们的编码方式。将字节转换成Unicode(也就是我们常用的字符串形式)有很多种方法,这取决于这些字节是用什么编码的。

你无法仅仅从字节数据中得知编码方式,必须有人告诉你这些字节的编码是什么。

不过,有时候你可以根据经验做个猜测:

>>> import chardet
>>> s = '\xe7\x8e\xa9'
>>> chardet.detect(s)
{'confidence': 0.505, 'encoding': 'utf-8'}
>>> s.decode(chardet.detect(s)['encoding'])
u'\u73a9'
>>> print _
玩

现在,你应该在字节数据进入你的Python程序后,立刻把它们转换成Unicode,这样你的代码就完全是在处理Unicode,而不是字节数据。

然后,你可以这样写文件:

import io
with io.open('/tmp/myfile.txt', 'wb', encoding='utf-8') as f:
    f.write(u'\u73a9')
    f.write('\n')
    f.write('random other data 12345...')
1

这里有一段对我有效的代码示例:

with open('foo', 'w+') as f:
    f.write('\xe7\x8e\xa9')

foo 文件中,我有:

但是,我是用 UTF-8 编码打开 foo 的,所以它显示的是中文字符,而不是 Unicode 值。

我用 vim 和 gedit 测试过,效果都很好。

也许你应该提供一下你的输出文件类型,这样我们可以更具体一些。

编辑

我现在明白问题出在哪里了。你在写字符串时用了 %r 标志。你应该用 %s(并再次启用编码)。

这里有一个有效的示例:

>>> a = u'\u7aef\u5e84\u7684\u9a6c\u6b47\u5c14'
>>> f = open('tmp', 'w')
>>> a = a.encode('utf-8')
>>> f.write('\t$$%r$$other_data\n'%a)
>>> f.write('\t$$%s$$other_data\n'%a)
>>> f.close

结果是:

    $$'\xe7\xab\xaf\xe5\xba\x84\xe7\x9a\x84\xe9\xa9\xac\xe6\xad\x87\xe5\xb0\x94'$$other_data
    $$端庄的马歇尔$$other_data

请查看 这个回答,了解 %r 和 %s 之间的区别。

希望这对你有帮助。

撰写回答