Ви натрапили на загальну проблему з кодуваннями: Як я можу сказати, в якому кодуванні знаходиться файл?
Відповідь: Ви не можете, якщо формат файлів не передбачає цього. Наприклад, 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, він повинен використовувати деякі засоби втечі. У своєму редакторі ви не повинні вводити рядок відображення, що відображається, але що означає рядок (у цьому випадку ви повинні ввести umlaut та зберегти файл).
Це означає, що ви можете використовувати функцію 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
має стати "à", але комп'ютер не має можливості знати, ви повинні сказати це, вказавши кодування, яке було використано під час запису файлу.