Я знаю, что существует довольно много решений для этой проблемы, но мой характерен в том смысле, что я мог бы получить усеченные данные 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
Чтобы переносить ошибки, вы можете использовать необязательный второй аргумент для метода декодирования строки byte-. В этом примере висячий третий байт ('c') заменяется символом замены U+ FFFD:
>>> 'abc'.decode('UTF-16', 'replace')
u'\u6261\ufffd'
Существует также опция "игнорировать", которая просто удаляет байты, которые невозможно декодировать:
>>> 'abc'.decode('UTF-16', 'ignore')
u'\u6261'
Хотя принято желать, чтобы система, "толерантная" к некорректно закодированному тексту, часто бывает трудно определить, каково ожидаемое поведение в этих ситуациях. Вы можете обнаружить, что тот, кто предоставил требование "иметь дело с" неправильно закодированным текстом, не полностью понимает концепцию кодирования символов.
Как насчет:
data = open(filename).read()
try:
data = data.decode("utf-16")
except UnicodeDecodeError:
data = data[:-1].decode("utf-16")
т.е. если он обрезал mid- через блок кода, отключите последний байт и сделайте это снова. Это вернет вас к действительной строке UTF- 16, без необходимости пытаться реализовать декодер самостоятельно.
Это просто подпрыгнуло на меня как улучшение "лучшей практики". Доступ к файлам действительно должен быть обернут в блоки with
. Это поможет вам открыть и очистить.
open(filename).close()
- пустая трата времени - он снова открывает файл, а затем сразу же закрывает новый дескриптор файла.