2008-10-06 3 views
20

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

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

ответ

41

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

This blog рекомендует модуль 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' 
11

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

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

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

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

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

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

+1

Спасибо, что указал на потенциальные проблемы. Однако я не рискую иметь неконвертируемые символы Юникода в содержимом выходного файла.Он просто выводит схему SQL внутренней базы данных и не содержит каких-либо символов вне обычного, то есть за пределами ASCII. – 2008-10-06 17:35:33

+1

@Ray Vega: Это вы знаете прямо сейчас. Это ошибка и потенциальная ошибка, предполагающая, что данные Unicode будут иметь только символы ASCII. – 2011-09-01 18:00:09

2

Как это:

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

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

EDIT: Как только указал Пит Карл, между Unicode и ASCII нет однозначного отображения. Поэтому некоторые символы просто не могут быть преобразованы в режиме сохранения информации. Более того, стандартный ASCII является более или менее подмножеством UTF-8, поэтому вам даже не нужно делать декодирование.

2

Вот некоторые простые (и глупые) код, чтобы сделать перевод кодирования. Я предполагаю (но не должен), чтобы входной файл находился в 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))) 

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

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

Заканчивать the docs для более простых вариантов. Если вам нужно сделать что-нибудь более сложное, вы можете проверить The UNICODE Hammer в Поваренной книге Python.

0

Важно отметить, что формат файлов Unicode отсутствует. 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.

0

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

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

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

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

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

myasciistring = (mystring.encode('ASCII')) 
type(myasciistring) 
    <type 'str'> 
2

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

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

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

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