Vous êtes tombé sur le problème général des encodages: comment savoir dans quel encodage se trouve un fichier?
Réponse: Vous ne pouvez pas sauf si le format de fichier le prévoit. XML, par exemple, commence par:
<?xml encoding="utf-8"?>
Cet en-tête a été soigneusement choisi afin qu'il puisse être lu quel que soit l'encodage. Dans votre cas, il n'y a pas un tel indice, donc ni votre éditeur ni Python n'ont la moindre idée de ce qui se passe. Par conséquent, vous devez utiliser le codecs
module et utiliser celui codecs.open(path,mode,encoding)
qui fournit le bit manquant en Python.
Quant à votre éditeur, vous devez vérifier s'il offre un moyen de définir l'encodage d'un fichier.
L'utilité de l'UTF-8 est de pouvoir encoder des caractères 21 bits (Unicode) en tant que flux de données 8 bits (car c'est la seule chose que tous les ordinateurs du monde peuvent gérer). Mais comme la plupart des systèmes d'exploitation sont antérieurs à l'ère Unicode, ils ne disposent pas d'outils appropriés pour attacher les informations d'encodage aux fichiers sur le disque dur.
Le problème suivant est la représentation en Python. Ceci est parfaitement expliqué dans le commentaire de heikogerlach . Vous devez comprendre que votre console ne peut afficher que ASCII. Pour afficher Unicode ou quoi que ce soit> = charcode 128, il doit utiliser un moyen de s'échapper. Dans votre éditeur, vous ne devez pas taper la chaîne d'affichage échappée mais ce que signifie la chaîne (dans ce cas, vous devez saisir le tréma et enregistrer le fichier).
Cela dit, vous pouvez utiliser la fonction Python eval () pour transformer une chaîne échappée en chaîne:
>>> x = eval("'Capit\\xc3\\xa1n\\n'")
>>> x
'Capit\xc3\xa1n\n'
>>> x[5]
'\xc3'
>>> len(x[5])
1
Comme vous pouvez le voir, la chaîne "\ xc3" a été transformée en un seul caractère. Il s'agit maintenant d'une chaîne de 8 bits, encodée en UTF-8. Pour obtenir Unicode:
>>> x.decode('utf-8')
u'Capit\xe1n\n'
Gregg Lind a demandé: Je pense qu'il manque des morceaux ici: le fichier f2 contient: hex:
0000000: 4361 7069 745c 7863 335c 7861 316e Capit\xc3\xa1n
codecs.open('f2','rb', 'utf-8')
, par exemple, les lit tous dans des caractères séparés (attendu) Existe-t-il un moyen d'écrire dans un fichier en ASCII qui fonctionnerait?
Réponse: Cela dépend de ce que vous voulez dire. ASCII ne peut pas représenter des caractères> 127. Il vous faut donc un moyen de dire "les prochains caractères signifient quelque chose de spécial", ce que fait la séquence "\ x". Il dit: Les deux caractères suivants sont le code d'un seul caractère. "\ u" fait de même en utilisant quatre caractères pour encoder Unicode jusqu'à 0xFFFF (65535).
Vous ne pouvez donc pas écrire directement Unicode en ASCII (car ASCII ne contient tout simplement pas les mêmes caractères). Vous pouvez l'écrire comme des échappements de chaîne (comme dans f2); dans ce cas, le fichier peut être représenté en ASCII. Ou vous pouvez l'écrire en UTF-8, auquel cas, vous avez besoin d'un flux sécurisé 8 bits.
Votre solution en utilisant decode('string-escape')
fonctionne, mais vous devez être conscient de la quantité de mémoire que vous utilisez: trois fois la quantité d'utilisation codecs.open()
.
N'oubliez pas qu'un fichier n'est qu'une séquence d'octets de 8 bits. Ni les bits ni les octets n'ont de sens. C'est vous qui dites "65 signifie 'A'". Puisque \xc3\xa1
devrait devenir "à" mais que l'ordinateur n'a aucun moyen de le savoir, vous devez le lui dire en précisant l'encodage qui a été utilisé lors de l'écriture du fichier.