Как мне преобразовать формат файла из Unicode в ASCII, используя Python? - PullRequest
22 голосов
/ 06 октября 2008

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

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

Ответы [ 8 ]

44 голосов
/ 06 октября 2008

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

Этот блог рекомендует модуль <a href="http://www.python.org/doc/2.5.2/lib/module-unicodedata.html" rel="noreferrer">unicodedata </a>, который, по-видимому, заботится о грубом преобразовании символов без прямых соответствующих значений 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'
11 голосов
/ 06 октября 2008

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

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

3 голосов
/ 17 декабря 2011

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

iconv -f utf8 -t ascii <input.txt >output.txt
2 голосов
/ 11 июня 2011

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

    import unicodedata
    input = open(filename).read().decode('UTF-16')
    output = unicodedata.normalize('NFKD', input).encode('ASCII', 'ignore')
2 голосов
/ 06 октября 2008

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

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.

2 голосов
/ 06 октября 2008

Как это:

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

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

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

0 голосов
/ 15 декабря 2009

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

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

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

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

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

myasciistring = (mystring.encode('ASCII'))
type(myasciistring)
    <type 'str'>
0 голосов
/ 07 октября 2008

Важно отметить, что отсутствует формат файла «Юникод». Юникод может быть закодирован в байтах несколькими различными способами. Чаще всего 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.

...