UTF-16到Ascii忽略十进制值大于127的字符

时间:2011-06-15 17:32:07

标签: python ascii utf-16

我知道这个问题有很多解决方案,但我的意思是,我可能会截断utf16数据并且必须尽最大努力处理解码和编码因UnicodeDecodeError而失败的转换。所以在python中提出了以下代码。 请让我知道您对如何改进它们以加快处理速度的评论。

    try:
        # conversion to ascii if utf16 data is formatted correctly
        input = open(filename).read().decode('UTF16')
        asciiStr = input.encode('ASCII', 'ignore')
        open(filename).close()
        return asciiStr
    except:
        # if fail with UnicodeDecodeError, then use brute force 
        # to decode truncated data
        try:
            unicode = open(filename).read()
            if (ord(unicode[0]) == 255 and ord(unicode[1]) == 254):
                print("Little-Endian format, UTF-16")
                leAscii = "".join([(unicode[i]) for i in range(2, len(unicode), 2) if 0 < ord(unicode[i]) < 127])
                open(filename).close()
                return leAscii
            elif (ord(unicode[0]) == 254 and ord(unicode[1]) == 255):
                print("Big-Endian format, UTF-16")
                beAscii = "".join([(unicode[i]) for i in range(3, len(unicode), 2) if 0 < ord(unicode[i]) < 127])
                open(filename).close()
                return beAscii
            else:
                open(filename).close()
                return None
        except:
            open(filename).close()
            print("Error in converting to ASCII")
            return None

3 个答案:

答案 0 :(得分:3)

怎么样:

data = open(filename).read()
try:
    data = data.decode("utf-16")
except UnicodeDecodeError:
    data = data[:-1].decode("utf-16")

即。如果它在代码单元中途被截断,则剪掉最后一个字节,然后重新执行。这应该让你回到有效的UTF-16字符串,而不必自己尝试实现解码器。

答案 1 :(得分:2)

为了容忍错误,您可以使用字节字符串的decode方法的可选第二个参数。在这个例子中,悬空的第三个字节('c')被替换为“替换字符”U + FFFD:

>>> 'abc'.decode('UTF-16', 'replace')
u'\u6261\ufffd'

还有一个'ignore'选项,它只会删除无法解码的字节:

>>> 'abc'.decode('UTF-16', 'ignore')
u'\u6261'

虽然通常希望系统“容忍”错误编码的文本,但通常很难准确定义在这些情况下预期行为是什么。您可能会发现提供“处理”错误编码文本的要求的人并不完全掌握字符编码的概念。

答案 2 :(得分:-1)

这只是作为“最佳实践”改进而跳出来的。文件访问应该真正包含在with块中。这将为您打开和清理。