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

1

Я знаю, что существует довольно много решений для этой проблемы, но мой характерен в том смысле, что я мог бы получить усеченные данные 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
  • 0
    Кстати, open(filename).close() - пустая трата времени - он снова открывает файл, а затем сразу же закрывает новый дескриптор файла.
Теги:
ascii
utf-16

3 ответа

2
Лучший ответ

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

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

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

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

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

3

Как насчет:

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

т.е. если он обрезал mid- через блок кода, отключите последний байт и сделайте это снова. Это вернет вас к действительной строке UTF- 16, без необходимости пытаться реализовать декодер самостоятельно.

  • 0
    Это не защитит вас от пар байтов, которые соответствуют неназначенной кодовой точке, зарезервированной кодовой точке, суррогатной кодовой точке и т. Д.
  • 0
    @wberry: Нет, но если вы ожидаете действительный UTF-16, за исключением случаев, когда он урезан, вы можете захотеть сделать это, чтобы вы по-прежнему получали ошибки для неверного ввода. Вопрос был конкретно об укороченном UTF-16.
-1

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню