Как мне преобразовать формат файла из Unicode в ASCII с помощью Python?

StackOverflow https://stackoverflow.com/questions/175240

Вопрос

Я использую сторонний инструмент, который выводит файл в формате Unicode.Однако я предпочитаю, чтобы это было в формате ASCII.Инструмент не имеет настроек для изменения формата файла.

Каков наилучший способ преобразовать весь формат файла с помощью Python?

Это было полезно?

Решение

Вы можете достаточно легко преобразовать файл, просто используя unicode функция, но вы столкнетесь с проблемами с символами Unicode без прямого эквивалента ASCII.

Этот блог рекомендует unicodedata ( кодированные данные ) модуль, который, по-видимому, заботится о грубом преобразовании символов без прямого соответствия значениям ASCII, например

>>> title = u"Klüft skräms inför på fédéral électoral große"

обычно преобразуется в

Klft skrms infr p fdral lectoral groe

что довольно неправильно.Однако, используя unicodedata таким образом, результат может быть намного ближе к исходному тексту:

>>> import unicodedata
>>> unicodedata.normalize('NFKD', title).encode('ascii','ignore')
'Kluft skrams infor pa federal electoral groe'

Другие советы

Я думаю, что это более глубокая проблема, чем вы думаете . Простое изменение файла из Unicode в ASCII легко, однако, получить все символы Unicode для преобразования в приемлемые аналоги ASCII (многие буквы недоступны в обеих кодировках) - это другое.

Это руководство по Python Unicode может дать вам лучшее представление о том, что происходит со строками Unicode, которые переводятся в ASCII: http://www.reportlab.com/i18n/python_unicode_tutorial.html

Вот полезная цитата с сайта:

  

Python 1.6 также получает "Юникод"   встроенная функция, к которой вы можете   укажите кодировку:

> >>> unicode('hello') u'hello'
> >>> unicode('hello', 'ascii') u'hello'
> >>> unicode('hello', 'iso-8859-1') u'hello'
> >>>
  

Все три из них возвращают одинаковые   вещь, так как символы в «Привет»   являются общими для всех трех кодировок.

     

Теперь давайте закодируем что-то   Европейский акцент, который находится за пределами   ASCII. То, что вы видите на консоли, может   зависит от вашей операционной системы   локали; Windows позволяет мне печатать   ISO-Latin-1.

> >>> a = unicode('André','latin-1')
> >>> a u'Andr\202'
  

Если вы не можете набрать острую букву е,   Вы можете ввести строку «Andr \ 202»,   что однозначно.

     

Юникод поддерживает все общее   такие операции, как итерация и   расщепление. Мы не будем на них бегать   здесь.

Кстати, это команда linux iconv , которая выполняет эту работу.

iconv -f utf8 -t ascii <input.txt >output.txt

Вот простой (и глупый) код для перевода кодировки. Я предполагаю (но вы не должны), что входной файл находится в UTF-16 (Windows называет это просто «Юникод»).

input_codec = 'UTF-16'
output_codec = 'ASCII'

unicode_file = open('filename')
unicode_data = unicode_file.read().decode(input_codec)
ascii_file = open('new filename', 'w')
ascii_file.write(unicode_data.write(unicode_data.encode(output_codec)))

Обратите внимание, что это не будет работать, если в файле Unicode есть какие-либо символы, которые также не являются символами ASCII. Вы можете сделать следующее, чтобы превратить нераспознанные символы в '?':

ascii_file.write(unicode_data.write(unicode_data.encode(output_codec, 'replace')))

В документации вы найдете более простые варианты. Если вам нужно сделать что-нибудь более сложное, вы можете ознакомиться с молотком UNICODE по адресу поваренная книга Python.

Вот так:

uc = open(filename).read().decode('utf8')
ascii = uc.decode('ascii')

Однако обратите внимание, что это завершится неудачей с исключением UnicodeDecodeError , если есть какие-либо символы, которые нельзя преобразовать в ASCII.

РЕДАКТИРОВАТЬ: Как только что отметил Пит Карл, не существует однозначного отображения из Unicode в ASCII. Поэтому некоторые символы просто не могут быть преобразованы в способ сохранения информации. Более того, стандартный ASCII является более или менее подмножеством UTF-8, поэтому вам даже не нужно ничего декодировать.

Для моей проблемы, когда я просто хотел пропустить символы не-ascii и просто выводить только вывод ascii, приведенное ниже решение сработало очень хорошо:

    import unicodedata
    input = open(filename).read().decode('UTF-16')
    output = unicodedata.normalize('NFKD', input).encode('ASCII', 'ignore')

Важно отметить, что отсутствует формат файла 'Unicode'. Юникод может быть закодирован в байтах несколькими различными способами. Чаще всего UTF-8 или UTF-16. Вам нужно будет знать, какой из этих инструментов выдает сторонний инструмент. Если вы знаете, что преобразование между различными кодировками довольно просто:

in_file = open("myfile.txt", "rb")
out_file = open("mynewfile.txt", "wb")

in_byte_string = in_file.read()
unicode_string = bytestring.decode('UTF-16')
out_byte_string = unicode_string.encode('ASCII')

out_file.write(out_byte_string)
out_file.close()

Как отмечалось в других ответах, вы, вероятно, захотите предоставить обработчик ошибок для метода кодирования. Использовать 'replace' в качестве обработчика ошибок очень просто, но он искажает ваш текст, если он содержит символы, которые не могут быть представлены в ASCII.

Как отмечали другие постеры, ASCII является подмножеством unicode.

Однако, если вы:

  • у вас есть устаревшее приложение
  • вы не контролируете код для этого приложения
  • вы уверены, что ваш ввод попадает в подмножество ASCII

Тогда приведенный ниже пример показывает, как это сделать:

mystring = u'bar'
type(mystring)
    <type 'unicode'>

myasciistring = (mystring.encode('ASCII'))
type(myasciistring)
    <type 'str'>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top