Natknąłeś się na ogólny problem z kodowaniem: Jak mogę stwierdzić, w którym kodowaniu jest plik?
Odpowiedź: Nie możesz tego zrobić, chyba że format pliku to zapewnia. Na przykład XML zaczyna się od:
<?xml encoding="utf-8"?>
Ten nagłówek został starannie wybrany, aby można go było odczytać bez względu na kodowanie. W twoim przypadku nie ma takiej wskazówki, dlatego ani twój redaktor, ani Python nie mają pojęcia, co się dzieje. Dlatego musisz użyć codecs
modułu i użyćcodecs.open(path,mode,encoding)
który zapewnia brakujący bit w Pythonie.
Jeśli chodzi o edytor, musisz sprawdzić, czy oferuje on sposób na ustawienie kodowania pliku.
Celem UTF-8 jest możliwość kodowania 21-bitowych znaków (Unicode) jako 8-bitowego strumienia danych (ponieważ jest to jedyna rzecz, którą wszystkie komputery na świecie mogą sobie poradzić). Ponieważ jednak większość systemów operacyjnych pochodzi z epoki Unicode, nie mają one odpowiednich narzędzi do dołączania informacji o kodowaniu do plików na dysku twardym.
Kolejnym problemem jest reprezentacja w Pythonie. To doskonale wyjaśniono w komentarzu heikogerlach . Musisz zrozumieć, że twoja konsola może wyświetlać tylko ASCII. Aby wyświetlić Unicode lub cokolwiek> = kod znakowy 128, musi użyć jakiegoś sposobu zmiany znaczenia. W edytorze nie wolno wpisywać uciekającego łańcucha wyświetlanego, ale jego znaczenie (w tym przypadku należy wprowadzić umlaut i zapisać plik).
To powiedziawszy, możesz użyć funkcji eval () Pythona, aby przekształcić łańcuch znaków w ciąg znaków:
>>> x = eval("'Capit\\xc3\\xa1n\\n'")
>>> x
'Capit\xc3\xa1n\n'
>>> x[5]
'\xc3'
>>> len(x[5])
1
Jak widać, ciąg „\ xc3” został przekształcony w pojedynczy znak. Jest to teraz 8-bitowy ciąg kodowany w UTF-8. Aby uzyskać Unicode:
>>> x.decode('utf-8')
u'Capit\xe1n\n'
Gregg Lind zapytał: Myślę, że brakuje tutaj niektórych elementów: plik f2 zawiera: hex:
0000000: 4361 7069 745c 7863 335c 7861 316e Capit\xc3\xa1n
codecs.open('f2','rb', 'utf-8')
, na przykład czyta je wszystkie w osobnych znakach (oczekiwane) Czy istnieje jakiś sposób zapisu do pliku w ASCII, który by działał?
Odpowiedź: To zależy od tego, co masz na myśli. ASCII nie może reprezentować znaków> 127. Dlatego potrzebujesz sposobu, aby powiedzieć „kilka następnych znaków oznacza coś specjalnego”, co robi sekwencja „\ x”. Mówi: Następne dwa znaki to kod jednego znaku. „\ u” robi to samo, używając czterech znaków do kodowania Unicode do 0xFFFF (65535).
Nie możesz więc bezpośrednio pisać Unicode do ASCII (ponieważ ASCII po prostu nie zawiera tych samych znaków). Możesz pisać jako znaki ucieczki (jak w f2); w takim przypadku plik może być reprezentowany jako ASCII. Możesz też napisać go jako UTF-8, w takim przypadku potrzebujesz 8-bitowego bezpiecznego strumienia.
Użyte rozwiązanie decode('string-escape')
działa, ale musisz pamiętać, ile pamięci zużywasz: trzy razy więcej niż używaszcodecs.open()
.
Pamiętaj, że plik jest tylko sekwencją bajtów z 8 bitami. Ani bity, ani bajty nie mają znaczenia. To ty mówisz „65” oznacza „A”. Ponieważ \xc3\xa1
powinno stać się „à”, ale komputer nie ma możliwości wiedzieć, musisz to powiedzieć, określając kodowanie, które zostało użyte podczas zapisywania pliku.