Bạn đã vấp phải vấn đề chung với mã hóa: Làm thế nào tôi có thể biết mã hóa tệp là gì?
Trả lời: Bạn không thể trừ khi định dạng tệp cung cấp cho việc này. XML, ví dụ, bắt đầu bằng:
<?xml encoding="utf-8"?>
Tiêu đề này đã được chọn cẩn thận để nó có thể được đọc bất kể mã hóa. Trong trường hợp của bạn, không có gợi ý nào như vậy, do đó, cả trình soạn thảo và Python của bạn đều không biết chuyện gì đang xảy ra. Do đó, bạn phải sử dụng codecs
mô-đun và sử dụng codecs.open(path,mode,encoding)
cung cấp bit bị thiếu trong Python.
Đối với trình chỉnh sửa của bạn, bạn phải kiểm tra xem nó có cung cấp một số cách để đặt mã hóa của tệp không.
Quan điểm của UTF-8 là có thể mã hóa các ký tự 21 bit (Unicode) dưới dạng luồng dữ liệu 8 bit (vì đó là điều duy nhất mà tất cả các máy tính trên thế giới có thể xử lý). Nhưng vì hầu hết các hệ điều hành trước thời đại Unicode, chúng không có các công cụ phù hợp để đính kèm thông tin mã hóa vào các tệp trên đĩa cứng.
Vấn đề tiếp theo là sự đại diện trong Python. Điều này được giải thích hoàn hảo trong bình luận của heikogerlach . Bạn phải hiểu rằng bảng điều khiển của bạn chỉ có thể hiển thị ASCII. Để hiển thị Unicode hoặc bất cứ thứ gì> = charcode 128, nó phải sử dụng một số phương tiện để thoát. Trong trình chỉnh sửa của bạn, bạn không được nhập chuỗi hiển thị đã thoát nhưng chuỗi đó có nghĩa là gì (trong trường hợp này, bạn phải nhập ô và lưu tệp).
Điều đó nói rằng, bạn có thể sử dụng hàm Python eval () để biến một chuỗi thoát thành chuỗi:
>>> x = eval("'Capit\\xc3\\xa1n\\n'")
>>> x
'Capit\xc3\xa1n\n'
>>> x[5]
'\xc3'
>>> len(x[5])
1
Như bạn có thể thấy, chuỗi "\ xc3" đã được biến thành một ký tự. Đây là một chuỗi 8 bit, được mã hóa UTF-8. Để có được Unicode:
>>> x.decode('utf-8')
u'Capit\xe1n\n'
Gregg Lind hỏi: Tôi nghĩ có một số phần bị thiếu ở đây: tệp f2 chứa: hex:
0000000: 4361 7069 745c 7863 335c 7861 316e Capit\xc3\xa1n
codecs.open('f2','rb', 'utf-8')
, ví dụ, đọc tất cả chúng trong một ký tự riêng (dự kiến) Có cách nào để ghi vào một tệp trong ASCII sẽ hoạt động không?
Trả lời: Điều đó phụ thuộc vào ý của bạn. ASCII không thể biểu thị các ký tự> 127. Vì vậy, bạn cần một số cách để nói "một vài ký tự tiếp theo có nghĩa là một cái gì đó đặc biệt", đó là những gì chuỗi "\ x" làm. Nó nói: Hai ký tự tiếp theo là mã của một ký tự. "\ u" thực hiện tương tự bằng cách sử dụng bốn ký tự để mã hóa Unicode lên đến 0xFFFF (65535).
Vì vậy, bạn không thể trực tiếp viết Unicode sang ASCII (vì ASCII đơn giản là không chứa cùng các ký tự). Bạn có thể viết nó dưới dạng chuỗi thoát (như trong f2); trong trường hợp này, tệp có thể được biểu diễn dưới dạng ASCII. Hoặc bạn có thể viết nó dưới dạng UTF-8, trong trường hợp đó, bạn cần một luồng an toàn 8 bit.
Giải pháp sử dụng của bạn decode('string-escape')
không hoạt động, nhưng bạn phải nhận thức được bạn sử dụng bao nhiêu bộ nhớ: Ba lần lượng sử dụng codecs.open()
.
Hãy nhớ rằng một tệp chỉ là một chuỗi byte có 8 bit. Cả bit và byte đều không có nghĩa. Chính bạn là người nói "65 có nghĩa là" A ". Vì \xc3\xa1
sẽ trở thành "à" nhưng máy tính không có phương tiện để biết, bạn phải nói với nó bằng cách chỉ định mã hóa được sử dụng khi ghi tệp.