2010-01-27 22 views
20

Có ai biết làm thế nào để có được mã hóa của một tập tin bằng Python. Tôi biết rằng bạn có thể sử dụng các mô-đun codec để mở một tập tin với một mã hóa cụ thể nhưng bạn phải biết nó trước.Làm cách nào để biết mã hóa của một tệp bằng Python?

import codecs 
f = codecs.open("file.txt", "r", "utf-8") 

Có cách nào để tự động phát hiện mã hóa nào được sử dụng cho tệp không?

Cảm ơn trước

Edit: Cảm ơn tất cả mọi người cho answsers rất thú vị. Bạn cũng có thể quan tâm bởi http://whatismyencoding.com/ mà là dựa trên chardet (nhiều hơn các trang web được cung cấp bởi chai khuôn khổ python)

Trả lời

19

Rất tiếc, không có cách 'xác thực' để xác định mã hóa tệp bằng cách xem chính tệp đó. Đây là một vấn đề phổ quát, không giới hạn ở python hoặc bất kỳ hệ thống tệp cụ thể nào.

Nếu bạn đang đọc tệp XML, dòng đầu tiên trong tệp có thể cho bạn biết mã hóa là gì.

Nếu không, bạn sẽ phải sử dụng một số phương pháp dựa trên heuristics như chardet (một trong các giải pháp được đưa ra trong các câu trả lời khác) để đoán mã hóa bằng cách kiểm tra dữ liệu trong tệp ở định dạng byte thô. Nếu bạn đang sử dụng Windows, tôi tin rằng Windows API cũng đưa ra các phương pháp để thử và đoán mã hóa dựa trên dữ liệu trong tệp.

3

Unicode Dammit từ Beautiful Soup, sử dụng chardet nhưng thêm một vài tính năng bổ sung.

Nó cố đọc mã hóa từ bên trong tệp XML hoặc HTML. Sau đó, nó cố gắng tìm kiếm một BOM hoặc một cái gì đó như thế ở đầu của tập tin. Nếu nó không thể làm điều đó, nó sử dụng chardet.

3

Đây là một đoạn mã nhỏ để giúp bạn đoán mã hóa. Nó đoán giữa latin1 và utf8 khá tốt. Nó chuyển đổi một chuỗi byte thành một chuỗi unicode.

# Attention: Order of encoding_guess_list is import. Example: "latin1" always succeeds. 
encoding_guess_list=['utf8', 'latin1'] 
def try_unicode(string, errors='strict'): 
    if isinstance(string, unicode): 
     return string 
    assert isinstance(string, str), repr(string) 
    for enc in encoding_guess_list: 
     try: 
      return string.decode(enc, errors) 
     except UnicodeError, exc: 
      continue 
    raise UnicodeError('Failed to convert %r' % string) 
def test_try_unicode(): 
    for start, should in [ 
     ('\xfc', u'ü'), 
     ('\xc3\xbc', u'ü'), 
     ('\xbb', u'\xbb'), # postgres/psycopg2 latin1: RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 
     ]: 
     result=try_unicode(start, errors='strict') 
     if not result==should: 
      raise Exception(u'Error: start=%r should=%r result=%r' % (
        start, should, result)) 
+0

Ý tưởng tuyệt vời. Cảm ơn. –

+0

Tôi đã đơn giản hóa và điều chỉnh điều này một chút, chỉ bằng cách sử dụng .decode() trong một lần thử, ngoại trừ việc xảy ra khi (1) chuyển đổi thành công hoặc (2) sau khi hết bảng mã_guess_list. Nếu kết thúc là một thất bại, sau đó tôi áp dụng một khác nhau .decode() với các lỗi thiết lập để 'thay thế' thay vì 'nghiêm ngặt'. – JDM

1
#!/usr/bin/python 

""" 
Line by line detecting encoding if input and then convert it into UTF-8 
Suitable for look at logs with mixed encoding (i.e. from mail systems) 

""" 

import sys 
import chardet 

while 1: 
     l = sys.stdin.readline() 
     e = chardet.detect(l) 

     u = None 
     try: 
       if e['confidence'] > 0.3: 
         u = unicode(l, e['encoding']) 
     except: 
       pass 

     if u: 
       print u, 
     else: 
       print l, 
Các vấn đề liên quan