UTF-16 для Ascii игнорирует символы с десятичным значением больше 127 - PullRequest
1 голос
/ 15 июня 2011

Я знаю, что есть довольно много решений для этой проблемы, но мое было странным в том смысле, что я мог бы получить усеченные данные 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 ]

3 голосов
/ 15 июня 2011

Как насчет:

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

Т.е., если оно усекается посередине кодовой единицы, отрежьте последний байт и сделайте это снова.Это должно вернуть вас к правильной строке UTF-16, не пытаясь самостоятельно реализовать декодер.

2 голосов
/ 15 июня 2011

Чтобы допустить ошибки, вы можете использовать дополнительный второй аргумент метода декодирования байтовой строки. В этом примере болтающийся третий байт ('c') заменяется на "символ замены" U + FFFD:

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

Существует также опция игнорирования, которая просто отбрасывает байты, которые не могут быть декодированы:

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

Хотя обычно требуется система, которая «терпима» к неправильно закодированному тексту, часто довольно сложно точно определить, каково ожидаемое поведение в этих ситуациях. Вы можете обнаружить, что тот, кто предоставил требование «иметь дело с» неправильно закодированным текстом, не полностью понимает концепцию кодировки символов.

0 голосов
/ 15 июня 2011

Это просто выскочило на меня как улучшение "лучшей практики". Доступ к файлам должен быть заключен в блоки with. Это будет обрабатывать открытие и очистку для вас.

...