2013-11-04 85 views
7

我想從一個文本文件中刪除所有非ASCII字符使用unidecode。我發現一個應該這樣做的軟件包,它應該接受一個字符串並將所有非ASCII字符轉換爲最接近的ascii字符。我曾經在Perl很輕鬆了這個相同的模塊通過只調用while (<input>) { $_ = unidecode($_); }而這一次是Perl模塊的直接端口,該文件表明,它應該工作一樣。如何在Python(3.3)

我敢肯定,這是簡單的東西,我只是不足夠的瞭解性格和文件編碼就知道是什麼問題。我的原始文件以UTF-8編碼(從UCS-2LE轉換而來)。這個問題可能與我缺乏編碼知識和處理字符串錯誤比模塊有關,希望有人可以解釋爲什麼。我已經嘗試了我所知道的一切,而不僅僅是隨機插入代碼,並且搜索到目前爲止我沒有運氣的錯誤。

這裏是我的Python

from unidecode import unidecode 

def toascii(): 
    origfile = open(r'C:\log.convert', 'rb') 
    convertfile = open(r'C:\log.toascii', 'wb') 

    for line in origfile: 
     line = unidecode(line) 
     convertfile.write(line) 

    origfile.close() 
    convertfile.close() 

toascii(); 

如果我不開在字節模式(origfile = open('file.txt','r')原文件,然後我從for line in origfile:線錯誤UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 1563: character maps to <undefined>

如果我確實打開它在字節模式'rb'我從line = unidecode(line)行獲得TypeError: ord() expected string length 1, but int found行。

如果我將行聲明爲字符串line = unidecode(str(line))那麼它將寫入該文件,但是...不正確。 \r\n'b'\xef\xbb\xbf[ 2013.10.05 16:18:01 ] User_Name > .\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\寫出\ n,\ r等和unicode字符,而不是將它們轉換爲任何東西。

如果我轉換線串如上,並打開字節模式convertfile 'wb'它給人的錯誤TypeError: 'str' does not support the buffer interface

如果我在字節模式下打開未聲明的字符串'wb'unidecode(line)然後我得到的再次出現TypeError: ord() expected string length 1, but int found錯誤。

回答

8

unidecode模塊接受的Unicode字符串值和回報在Python 3.你給它的二進制數據,而不是一個unicode字符串。解碼爲Unicode或打開文本方式輸入文本文件,並將其寫入文件之前,結果編碼爲ASCII,或打開在文本模式下,輸出的文本文件。

從模塊文件引用:

The module exports a single function that takes an Unicode object (Python 2.x) or string (Python 3.x) and returns a string (that can be encoded to ASCII bytes in Python 3.x)

重點煤礦。

這應該工作:

def toascii(): 
    with open(r'C:\log.convert', 'r', encoding='utf8') as origfile, open(r'C:\log.toascii', 'w', encoding='ascii') as convertfile: 
     for line in origfile: 
      line = unidecode(line) 
      convertfile.write(line) 

這將打開inputfile中的文本作案(使用UTF8編碼,它通過你的樣品線判斷是正確的),並在文本作案(編碼ASCII)寫道。

你需要明確指定要打開的文件的編碼;如果省略則使用當前系統區域設置的編碼,通常不會是正確的編解碼器,如果你的代碼需要便攜式(一locale.getpreferredencoding(False)調用的結果)。

+0

首先嚐試它似乎沒有工作,我得到了與我使用str()時相同的問題,即我最終得到像\ r \ n \ xef \ xbb \ xbf這樣的行。儘管如此,我會去看看我能做些什麼。 – BeanBagKing

+1

@BeanBagKing:你看到的'b'\ xef \ xbb \ xbf''是一個字節值的表示;這意味着你傳遞的是'str(bytevalue)'的結果,而不是從輸入文件解碼的unicode字符串值。 –

+0

正確,不知何故我的原始文件被這些值覆蓋。儘管如此,我仍然遇到了錯誤,UnicodeDecodeError:'charmap'編解碼器無法解碼位置1563中的字節0x90:cha racter maps to '。如果我在字節模式下打開文件,我得到'期望的字符串長度爲1,但int找到了'這可能是我的原始文件的編碼更基本的問題? – BeanBagKing