2011-03-23 45 views
0

我正在使用Python 2.6.1在Windows上工作。編寫unicode UTF-16數據到Python中的文件問題

我有一個包含單一字符串Hello一個Unicode UTF-16的文本文件,如果我看它在一個二進制編輯器我看到:

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

我想要做的就是讀取這個文件,運行它通過谷歌翻譯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,並且首先將我的「Hello」的Unicode文件作爲UTF -16字符,然後是「Ahoj」作爲單字節ASCII字符。

我敢肯定我錯過了一些明顯的東西,但我看不見什麼。我試圖從查詢結果urllib.unquote(),但沒有幫助。我也嘗試打印字符串,因爲它回來了f.readlines(),它看起來很合理,但很難說,因爲我的終端窗口不能正確支持Unicode。

有什麼其他建議可以嘗試?我已經看過建議的模擬器,但它們都不符合我的設想。

+0

確實從谷歌的API的響應總是UTF-16?另外,爲什麼你使用'codecs'而不是簡單地寫'u'foo'.encode('utf-16')'到二進制模式打開的文件? – Cameron 2011-03-23 21:23:56

+0

您是否閱讀過['codecs.open()'文檔](http://docs.python.org/library/codecs.html#codecs.open)中的註釋?看起來你應該寫'unicode'對象(除了''\ n「''外你大部分都是這樣做的),並且你需要處理你自己的平臺特定的換行符(Windows上的CR LF)。 – Cameron 2011-03-23 21:29:24

回答

5

我相信谷歌的輸出是UTF-8,而不是UTF-16。嘗試此修復:

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

完美,謝謝!我誤解了unicode()函數中編碼參數的要點。 – Vicky 2011-03-23 21:43:15

+1

@Vicky,@Mark Ransom:在地毯下清除錯誤'errors ='ignore''不是一個好主意,除非你知道你在做什麼。在這種情況下,UTF-8解碼錯誤可能表明您解析響應的方法可能存在缺陷。 – 2011-03-24 00:30:58

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 
>>> 

看起來很接近我...