将不同的编码转换为ASCII

12 浏览
0 Comments

将不同的编码转换为ASCII

我有一百个文件,根据chardet的结果,每个文件都使用以下之一的编码:

['UTF-8', 'ascii', 'ISO-8859-2', 'UTF-16LE', 'TIS-620', 'utf-8', 'SHIFT_JIS', 'ISO-8859-7']

所以我知道文件的编码,因此我知道应该使用什么编码打开文件。

我希望将所有文件转换为仅包含ascii字符。我还希望将不同版本的字符如-'转换为它们的纯ascii等效字符。例如,b"\xe2\x80\x94".decode("utf8")应该转换为-。最重要的是文本易于阅读。例如,我不想要don t,而是想要don't

我应该如何做到这一点?

我可以使用Python 2或3来解决这个问题。

以下是我在Python 2中的代码进展。我试图检测那些起始字符为非ascii字符的行。

for file_name in os.listdir('.'):
        print(file_name)
        r = chardet.detect(open(file_name).read())
        charenc = r['encoding']
        with open(file_name,"r" ) as f:
            for line in f.readlines():
              if line.decode(charenc) != line.decode("ascii","ignore"):
                print(line.decode("ascii","ignore"))

这给我带来了以下异常:

    if line.decode(charenc) != line.decode("ascii","ignore"):
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/encodings/utf_16_le.py", line 16, in decode
    return codecs.utf_16_le_decode(input, errors, True)
UnicodeDecodeError: 'utf16' codec can't decode byte 0x0a in position 6: truncated data

0
0 Comments

在处理二进制文件时,不要使用.readlines()方法。在UTF-16小端编码中,换行符被编码为两个字节,分别是0A(ASCII中的换行符)和00(空字符)。.readlines()方法会根据这两个字节之间的第一个字节进行分割,导致解码时数据不完整。

为了便于解码,可以使用io库重新打开文件:

import io
for file_name in os.listdir('.'):
    print(file_name)
    r = chardet.detect(open(file_name).read())
    charenc = r['encoding']
    with io.open(file_name, "r", encoding=charenc) as f:
        for line in f:
            line = line.encode("ascii", "ignore"):
            print line

如果想要用ASCII友好的字符替换特定的Unicode码点,可以使用一个将码点映射到码点或Unicode字符串的字典,并首先调用line.translate()方法:

charmap = {
    0x2014: u'-',   # em dash
    0x201D: u'"',   # comma quotation mark, double
    # etc.
}
line = line.translate(charmap)

在这里,我使用十六进制整数字面量来定义要映射的Unicode码点。字典中的值可以是Unicode字符串、整数(码点)或None(表示完全删除该码点)。

当我在带有"ignore"的行上使用"encode()"时,会出现UnicodeEncodeError: 'ascii' codec can't encode character u'\ufeff' in position 0: ordinal not in range(128)的错误。charenc = "UTF-8"。

抱歉,这是我的错误;应该是使用encode(),而不是decode()

如果文件非常大(例如75GB),使用open(file_name).read()可能会有问题。可以使用open(file_name).readline()来解决。

0