将文件转换为Ascii会抛出异常

时间:2015-08-06 10:47:08

标签: python python-3.x unicode

由于my previous question,我编写了这个代码:

def ConvertFileToAscii(args, filePath):
    try:
       # Firstly, make sure that the file is writable by all, otherwise we can't update it
        os.chmod(filePath, 0o666)

        with open(filePath, "rb") as file:
            contentOfFile = file.read()

        unicodeData = contentOfFile.decode("utf-8")
        asciiData = unicodeData.encode("ascii", "ignore")

        asciiData = unicodedata.normalize('NFKD', unicodeData).encode('ASCII', 'ignore')

        temporaryFile = tempfile.NamedTemporaryFile(mode='wt', delete=False)
        temporaryFileName = temporaryFile.name

        with open(temporaryFileName, 'wb')  as file:
            file.write(asciiData)

        if ((args.info) or (args.diagnostics)):
            print(filePath + ' converted to ASCII and stored in ' + temporaryFileName)


        return temporaryFileName

    #
    except KeyboardInterrupt:
        raise

    except Exception as e:
        print('!!!!!!!!!!!!!!!\nException while trying to convert ' + filePath + ' to ASCII')
        print(e)
        exc_type, exc_value, exc_traceback = sys.exc_info()
        print(traceback.format_exception(exc_type, exc_value, exc_traceback))

        if args.break_on_error:
            sys.exit('Break on error\n')

当我运行它时,我会得到这样的例外:

['Traceback (most recent call last):
', '  File "/home/ker4hi/tools/xmlExpand/xmlExpand.py", line 99, in ConvertFileToAscii
    unicodeData = contentOfFile.decode("utf-8")
    ', "UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf6 in position 1081: invalid start byte"]

我做错了什么?

我真的不关心将数据丢失为ASCII的数据丢失。

ox9C是Ü一个带有变音符号(Umlaut)的U,我可以没有它。

如何将此类文件转换为仅包含纯Ascii字符?我真的需要打开它们作为bi8nary并检查每个字节吗?

4 个答案:

答案 0 :(得分:1)

使用:

contentOfFile.decode('utf-8', 'ignore')

例外来自 decode 阶段,您没有忽略该错误。

答案 1 :(得分:1)

0x00f6 ö(ouml)在ISO-8859-1中编码。我的猜测是你使用了错误的Unicode解码器。

尝试:unicodeData = contentOfFile.decode("ISO-8859-1")

答案 2 :(得分:1)

您无需在内存中加载整个文件并在其上调用.decode()open()encoding参数(在Python 2上使用io.open()):

with open(filename, encoding='ascii', errors='ignore') as file:
    ascii_char = file.read(1)

如果需要Unicode文本的ascii音译;考虑unidecode

答案 3 :(得分:1)

  

我真的不关心将数据丢失为ASCII的数据丢失。   ...   如何将这些文件转换为仅包含纯Ascii字符?

一种方法是使用decode方法的替换选项。 替换而不是忽略的优势在于您获得了缺失值的占位符,这有助于防止对文本的误解。

请务必使用ASCII编码而不是UTF-8。否则,当解码器尝试重新同步时,您可能会丢失相邻的ascii字符。

最后,在解码步骤后运行encode('ascii')。否则,您将使用unicode字符串而不是字节字符串。

>>> string_of_unknown_encoding = 'L\u00f6wis'.encode('latin-1')
>>> now_in_unicode = string_of_unknown_encoding.decode('ascii', 'replace')
>>> back_to_bytes = now_in_unicode.replace('\ufffd', '?').encode('ascii')
>>> type(back_to_bytes)
<class 'bytes'>
>>> print(back_to_bytes)
b'L?wis'

那就是说,TheRightWay™这样做是为了开始关注数据丢失并使用正确的编码(显然你的输入不是UTF-8,否则解码就不会失败):

>>> string_of_known_latin1_encoding = 'L\u00f6wis'.encode('latin-1')
>>> now_in_unicode = string_of_known_latin1_encoding.decode('latin-1')
>>> back_to_bytes = now_in_unicode.encode('ascii', 'replace')
>>> type(back_to_bytes)
<class 'bytes'>
>>> print(back_to_bytes)