在Python中写入Unicode UTF-16数据到文件的问题

1 投票
2 回答
3511 浏览
提问于 2025-04-16 14:17

我在Windows上使用Python 2.6.1。

我有一个Unicode UTF-16格式的文本文件,里面只包含一个字符串“Hello”。如果我用二进制编辑器查看这个文件,我会看到:

FF FE 48 00 65 00 6C 00 6C 00 6F 00 0D 00 0A 00
BOM   H     e     l     l     o     CR    LF

我想做的是读取这个文件,通过Google翻译API处理它,然后把原始内容和翻译结果写入一个新的Unicode UTF-16格式的文本文件。

我写了以下Python脚本(其实我写的比这个复杂,包含了更多的错误检查,但这里简化成一个最小的测试案例):

#!/usr/bin/python    
import urllib
import urllib2
import sys
import codecs

def translate(key, line, lang):
    ret = ""
    print "translating " + line.strip() + " into " + lang
    url = "https://www.googleapis.com/language/translate/v2?key=" + key + "&source=en&target=" + lang + "&q=" + urllib.quote(line.strip())
    f = urllib2.urlopen(url)
    for l in f.readlines():
        if l.find("translatedText") > 0 and l.find('""') == -1:
            a,b = l.split(":")
            ret = unicode(b.strip('"'), encoding='utf-16', errors='ignore')
            break
    return ret

rd_file_name = sys.argv[1]
rd_file = codecs.open(rd_file_name, encoding='utf-16', mode="r")
rd_file_new = codecs.open(rd_file_name+".new", encoding='utf-16', mode="w")
key_file = open("api.key","r")

key = key_file.readline().strip()

for line in rd_file.readlines():
    new_line = translate(key, line, "ja")
    rd_file_new.write(unicode(line) + "\n")
    rd_file_new.write(new_line)
    rd_file_new.write("\n")

运行这个脚本后,我得到了一个几乎是Unicode格式的文件,但里面多了一些额外的字节:

FF FE 48 00 65 00 6C 00 6C 00 6F 00 0D 00 0A 00 0A 00
20 22 E3 81 93 E3 82 93 E3 81 AB E3 81 A1 E3 81 AF 22 0A 00 

我看到20是一个空格,22是一个引号,我猜“E3”是一个转义字符,urllib2用它来表示下一个字符是UTF-16编码的?

如果我运行同样的脚本,但把目标语言改成“cs”(捷克语),而不是“ja”(日语),那么返回的结果都是ASCII格式,我得到的Unicode文件中“Hello”是UTF-16字符,而“Ahoj”则是单字节的ASCII字符。

我肯定我漏掉了一些明显的东西,但我看不出来。我尝试在查询结果上使用urllib.unquote(),但没有帮助。我还尝试打印f.readlines()返回的字符串,虽然看起来都很合理,但因为我的终端窗口不支持Unicode,所以很难判断。

还有其他建议可以尝试吗?我看过推荐的重复问题,但似乎没有一个完全符合我的情况。

2 个回答

2

这些E3字节并不是“转义字符”。如果没有文档可查,只能猜的话,最有可能的编码方式就是UTF-8。根据我在日本度过的一周假期的经验,我期待看到的内容大概是“konnichiwa”(你好)。

>>> response = "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x81\xAF"
>>> ucode = response.decode('utf8')
>>> print repr(ucode)
u'\u3053\u3093\u306b\u3061\u306f'
>>> import unicodedata
>>> for c in ucode:
...     print unicodedata.name(c)
...
HIRAGANA LETTER KO
HIRAGANA LETTER N
HIRAGANA LETTER NI
HIRAGANA LETTER TI
HIRAGANA LETTER HA
>>>

对我来说,看起来差不多……

5

我认为谷歌的输出是UTF-8格式,而不是UTF-16格式。你可以试试这个解决办法:

ret = unicode(b.strip('"'), encoding='utf-8', errors='ignore') 

撰写回答