2008-10-06 9 views

Trả lời

41

Bạn có thể chuyển đổi tệp một cách dễ dàng chỉ bằng cách sử dụng hàm unicode, nhưng bạn sẽ gặp sự cố với các ký tự Unicode không tương đương ASCII thẳng.

This blog đề xuất mô-đun unicodedata, có vẻ như quan tâm đến việc chuyển đổi các ký tự không có giá trị ASCII tương ứng trực tiếp, ví dụ:

>>> title = u"Klüft skräms inför på fédéral électoral große" 

thường chuyển đổi sang

Klft skrms infr p fdral lectoral groe 

mà là khá sai. Tuy nhiên, bằng cách sử dụng mô-đun unicodedata, kết quả có thể gần gũi hơn với văn bản gốc:

>>> import unicodedata 
>>> unicodedata.normalize('NFKD', title).encode('ascii','ignore') 
'Kluft skrams infor pa federal electoral groe' 
+0

Điều đó khá tốt, ngoại trừ (như đã nói) nó bỏ sót một vài ký tự. Đối với tiếng Latin-1, bạn cần có trường hợp đặc biệt Æ, Ð, Ø, Þ, æ, ð, ø, ß và þ. – giltay

+0

Fredrick Lundh đăng trên này, với một kịch bản đơn giản để xây dựng trên đầu trang của 'unicodedata' cho thay thế trường hợp đặc biệt: http://effbot.org/zone/unicode-convert.htm – rcoup

11

Tôi nghĩ đây là vấn đề sâu hơn bạn nhận ra. Tuy nhiên, việc thay đổi tệp từ Unicode thành ASCII rất dễ dàng, tuy nhiên, việc nhận tất cả các ký tự Unicode để dịch sang các đối tác ASCII hợp lý (nhiều chữ cái không có sẵn trong cả hai bảng mã) là một ký tự khác.

này Python Unicode hướng dẫn có thể cung cấp cho bạn một ý tưởng tốt hơn về những gì xảy ra với chuỗi Unicode được dịch sang ASCII: http://www.reportlab.com/i18n/python_unicode_tutorial.html

Dưới đây là một trích dẫn hữu ích từ trang web:

Python 1.6 cũng có chức năng tích hợp "unicode" , mà bạn có thể chỉ định mã hóa:

> >>> unicode('hello') u'hello' 
> >>> unicode('hello', 'ascii') u'hello' 
> >>> unicode('hello', 'iso-8859-1') u'hello' 
> >>> 

Tất cả ba trong số này trả lại cùng một điều , vì các ký tự trong 'Hello' là phổ biến cho cả ba mã hóa.

Bây giờ, hãy mã hóa thứ gì đó có dấu cách châu Âu là , nằm ngoài số ASCII. Những gì bạn thấy ở bảng điều khiển có thể phụ thuộc vào hệ điều hành của bạn ngôn ngữ; Windows cho phép tôi nhập ISO-Latin-1.

> >>> a = unicode('André','latin-1') 
> >>> a u'Andr\202' 

Nếu bạn không thể gõ một bức thư điện tử cấp tính, bạn có thể nhập chuỗi 'Andr \ 202', đó là rõ ràng.

Unicode hỗ trợ tất cả các hoạt động phổ biến như lặp lại và chia tách . Chúng tôi sẽ không chạy qua chúng tại đây.

+1

Cảm ơn bạn đã chỉ ra các vấn đề tiềm ẩn. Tuy nhiên, tôi không chạy nguy cơ có các ký tự unicode không chuyển đổi trong nội dung của tệp đầu ra.Nó chỉ xuất ra lược đồ SQL của một cơ sở dữ liệu nội bộ và không chứa bất kỳ ký tự nào trong số các ký tự thông thường ngoài ASCII. –

+1

@Ray Vega: Bạn biết ngay bây giờ. Đó là một sai lầm và lỗi tiềm năng để giả định rằng dữ liệu unicode sẽ chỉ bao giờ có các ký tự ASCII. –

2

Như thế này:

uc = open(filename).read().decode('utf8') 
ascii = uc.decode('ascii') 

Lưu ý, tuy nhiên, sẽ này thất bại với một ngoại lệ UnicodeDecodeError nếu có bất kỳ ký tự không thể được chuyển đổi sang ASCII.

EDIT: Như Pete Karl vừa chỉ ra, không có ánh xạ một-một từ Unicode đến ASCII. Vì vậy, một số ký tự đơn giản không thể được chuyển đổi theo cách bảo quản thông tin. Hơn nữa, tiêu chuẩn ASCII là nhiều hơn hoặc ít hơn một tập hợp con của UTF-8, vì vậy bạn thậm chí không thực sự cần phải làm bất kỳ giải mã.

2

Dưới đây là một số mã đơn giản (và ngu ngốc) để làm dịch mã hóa. Tôi giả định (nhưng bạn không nên) rằng các tập tin đầu vào là trong UTF-16 (Windows gọi này chỉ đơn giản là 'Unicode').

input_codec = 'UTF-16' 
output_codec = 'ASCII' 

unicode_file = open('filename') 
unicode_data = unicode_file.read().decode(input_codec) 
ascii_file = open('new filename', 'w') 
ascii_file.write(unicode_data.write(unicode_data.encode(output_codec))) 

Lưu ý rằng điều này sẽ không hoạt động nếu có bất kỳ ký tự nào trong tệp Unicode không phải là ký tự ASCII. Bạn có thể thực hiện các thao tác sau để tắt các ký tự không được nhận dạng thành '?' S:

ascii_file.write(unicode_data.write(unicode_data.encode(output_codec, 'replace'))) 

Kiểm tra the docs để có thêm lựa chọn đơn giản. Nếu bạn cần phải làm bất cứ điều gì phức tạp hơn, bạn có thể muốn kiểm tra The UNICODE Hammer tại Sổ tay Python.

0

Điều quan trọng cần lưu ý là không có định dạng tệp 'Unicode'. Unicode có thể được mã hóa thành byte theo nhiều cách khác nhau. Thông dụng nhất là UTF-8 hoặc UTF-16. Bạn sẽ cần phải biết công cụ bên thứ ba nào của bạn xuất ra. Khi bạn biết điều đó, việc chuyển đổi giữa các mã hóa khác nhau là khá dễ dàng:

in_file = open("myfile.txt", "rb") 
out_file = open("mynewfile.txt", "wb") 

in_byte_string = in_file.read() 
unicode_string = bytestring.decode('UTF-16') 
out_byte_string = unicode_string.encode('ASCII') 

out_file.write(out_byte_string) 
out_file.close() 

Như đã lưu ý trong các trả lời khác, có thể bạn sẽ muốn cung cấp trình xử lý lỗi cho phương thức mã hóa. Việc sử dụng 'thay thế' làm trình xử lý lỗi rất đơn giản, nhưng sẽ làm xáo trộn văn bản của bạn nếu nó chứa các ký tự không thể được biểu diễn bằng ASCII.

0

Như các áp phích khác đã lưu ý, ASCII là tập con của unicode.

Tuy nhiên nếu bạn:

  • có một ứng dụng di sản
  • bạn không kiểm soát mã cho ứng dụng đó
  • bạn chắc chắn đầu vào của bạn rơi vào ASCII tập con

Ví dụ dưới đây cho thấy cách thực hiện:

mystring = u'bar' 
type(mystring) 
    <type 'unicode'> 

myasciistring = (mystring.encode('ASCII')) 
type(myasciistring) 
    <type 'str'> 
2

Đối với vấn đề của tôi, nơi tôi chỉ muốn bỏ qua các nhân vật Non-ascii và chỉ ra chỉ ra ascii, giải pháp dưới đây đã làm việc thực sự tốt:

import unicodedata 
    input = open(filename).read().decode('UTF-16') 
    output = unicodedata.normalize('NFKD', input).encode('ASCII', 'ignore') 
3

Bằng cách này, những là một lệnh linux iconv để làm điều này loại công việc.

iconv -f utf8 -t ascii <input.txt >output.txt