Вы наткнулись на общую проблему с кодировками: как определить, в какой кодировке находится файл?
Ответ: Вы не можете, если формат файла не предусматривает это. Например, XML начинается с:
<?xml encoding="utf-8"?>
Этот заголовок был тщательно выбран, чтобы его можно было прочитать независимо от кодировки. В вашем случае такой подсказки нет, поэтому ни ваш редактор, ни Python не имеют ни малейшего представления о том, что происходит. Следовательно, вы должны использовать codecs
модуль и использовать codecs.open(path,mode,encoding)
который обеспечивает отсутствующий бит в Python.
Что касается вашего редактора, вы должны проверить, предлагает ли он какой-либо способ установить кодировку файла.
Суть UTF-8 в том, чтобы иметь возможность кодировать 21-битные символы (Unicode) как 8-битный поток данных (потому что это единственное, что могут обрабатывать все компьютеры в мире). Но поскольку большинство ОС предшествуют эпохе Unicode, у них нет подходящих инструментов для прикрепления информации о кодировке к файлам на жестком диске.
Следующая проблема - представление в Python. Это прекрасно объясняется в комментарии Heikogerlach . Вы должны понимать, что ваша консоль может отображать только ASCII. Чтобы отобразить Unicode или что-нибудь> = charcode 128, он должен использовать некоторые средства экранирования. В вашем редакторе вы не должны вводить экранированную строку отображения, но что означает эта строка (в этом случае вы должны ввести умлаут и сохранить файл).
Тем не менее, вы можете использовать функцию Python eval (), чтобы превратить экранированную строку в строку:
>>> x = eval("'Capit\\xc3\\xa1n\\n'")
>>> x
'Capit\xc3\xa1n\n'
>>> x[5]
'\xc3'
>>> len(x[5])
1
Как видите, строка "\ xc3" была превращена в один символ. Теперь это 8-битная строка в кодировке UTF-8. Чтобы получить Unicode:
>>> x.decode('utf-8')
u'Capit\xe1n\n'
Грегг Линд спросил: я думаю, что здесь не хватает некоторых частей: файл f2 содержит: hex:
0000000: 4361 7069 745c 7863 335c 7861 316e Capit\xc3\xa1n
codecs.open('f2','rb', 'utf-8')
например, читает их все в отдельных символах (ожидается) Есть ли способ записи в файл в ASCII, который будет работать?
Ответ: Это зависит от того, что вы имеете в виду. ASCII не может представлять символы> 127. Таким образом, вам нужно как-то сказать «следующие несколько символов означают что-то особенное», что и делает последовательность «\ x». Он говорит: следующие два символа - это код одного символа. «\ u» делает то же самое, используя четыре символа для кодирования Unicode до 0xFFFF (65535).
Таким образом, вы не можете напрямую писать Unicode в ASCII (потому что ASCII просто не содержит одинаковые символы). Вы можете написать это как строковые экранированные (как в f2); в этом случае файл может быть представлен как ASCII. Или вы можете записать его как UTF-8, в этом случае вам нужен 8-битный безопасный поток.
Ваше решение с использованием decode('string-escape')
работает, но вы должны знать, сколько памяти вы используете: в три раза больше использования codecs.open()
.
Помните, что файл - это просто последовательность байтов с 8 битами. Ни биты, ни байты не имеют значения. Это ты говоришь "65 означает" А "". Поскольку он \xc3\xa1
должен стать «à», но компьютер не имеет средств для этого, вы должны указать это, указав кодировку, которая использовалась при записи файла.