2008-10-10 8 views

Trả lời

44

Bạn có thể sử dụng codecs module, như thế này:

import codecs 
BLOCKSIZE = 1048576 # or some other, desired size in bytes 
with codecs.open(sourceFileName, "r", "your-source-encoding") as sourceFile: 
    with codecs.open(targetFileName, "w", "utf-8") as targetFile: 
     while True: 
      contents = sourceFile.read(BLOCKSIZE) 
      if not contents: 
       break 
      targetFile.write(contents) 

EDIT: thêm BLOCKSIZE tham số để kiểm soát kích thước chunk.

+3

Đọc() sẽ luôn đọc toàn bộ tệp - bạn có thể muốn .read (BLOCKSIZE), trong đó BLOCKSIZE là một số lượng phù hợp để đọc/ghi cùng một lúc. – Brian

+1

Đó là sự thật, cảm ơn bạn. Tôi sẽ sửa đổi ví dụ của tôi. – DzinX

25

này làm việc cho tôi trong một thử nghiệm nhỏ:

sourceEncoding = "iso-8859-1" 
targetEncoding = "utf-8" 
source = open("source") 
target = open("target", "w") 

target.write(unicode(source.read(), sourceEncoding).encode(targetEncoding)) 
+0

Thậm chí tốt hơn là chỉ định chế độ nhị phân. – Arafangion

+0

@Arafangion Tại sao chế độ nhị phân sẽ tốt hơn? Cảm ơn! –

+0

@ Honghe.Wu: Trên cửa sổ, chế độ văn bản là mặc định và điều đó có nghĩa là kết thúc dòng của bạn sẽ bị xáo trộn bởi hệ điều hành, điều bạn không muốn nếu bạn không chắc về mã hóa trên đĩa. – Arafangion

12

Cảm ơn đã trả lời, nó hoạt động!

Và kể từ khi các file nguồn là trong các định dạng khác nhau, tôi đã thêm một danh sách các định dạng nguồn sẽ bị xét xử theo thứ tự (sourceFormats), và trên UnicodeDecodeError tôi cố gắng định dạng tiếp theo:

from __future__ import with_statement 

import os 
import sys 
import codecs 
from chardet.universaldetector import UniversalDetector 

targetFormat = 'utf-8' 
outputDir = 'converted' 
detector = UniversalDetector() 

def get_encoding_type(current_file): 
    detector.reset() 
    for line in file(current_file): 
     detector.feed(line) 
     if detector.done: break 
    detector.close() 
    return detector.result['encoding'] 

def convertFileBestGuess(filename): 
    sourceFormats = ['ascii', 'iso-8859-1'] 
    for format in sourceFormats: 
    try: 
     with codecs.open(fileName, 'rU', format) as sourceFile: 
      writeConversion(sourceFile) 
      print('Done.') 
      return 
     except UnicodeDecodeError: 
     pass 

def convertFileWithDetection(fileName): 
    print("Converting '" + fileName + "'...") 
    format=get_encoding_type(fileName) 
    try: 
     with codecs.open(fileName, 'rU', format) as sourceFile: 
      writeConversion(sourceFile) 
      print('Done.') 
      return 
    except UnicodeDecodeError: 
     pass 

    print("Error: failed to convert '" + fileName + "'.") 


def writeConversion(file): 
    with codecs.open(outputDir + '/' + fileName, 'w', targetFormat) as targetFile: 
     for line in file: 
      targetFile.write(line) 

# Off topic: get the file list and call convertFile on each file 
# ... 

(EDIT bởi Rudro Badhon: điều này kết hợp thử nhiều định dạng ban đầu cho đến khi bạn không nhận được ngoại lệ cũng như phương pháp thay thế sử dụng chardet.universaldetector)

+0

Đối với những trường hợp khó khăn, bạn có thể thử phát hiện mã hóa với mô-đun chardet từ feedparser.org, nhưng trong trường hợp của bạn, đó là một quá mức cần thiết. – itsadok

+0

My Python 3.5 không nhận ra hàm 'file'. cái đó từ đâu tới? – physicalattraction

+0

Có, câu trả lời này đã được đăng cách đây 8 năm, do đó, nó là một đoạn mã Python 2 cũ. –

0

Để đoán mã hóa nguồn, bạn có thể sử dụng lệnh file * nix.

Ví dụ:

$ file --mime jumper.xml 

jumper.xml: application/xml; charset=utf-8 
+0

Nó không trả lời câu hỏi. –

0

Đây là một Python3 chức năng để chuyển đổi bất kỳ tập tin văn bản vào một với mã UTF-8. (không sử dụng các gói không cần thiết)

def correctSubtitleEncoding(filename, newFilename, encoding_from, encoding_to='UTF-8'): 
    with open(filename, 'r', encoding=encoding_from) as fr: 
     with open(newFilename, 'w', encoding=encoding_to) as fw: 
      for line in fr: 
       fw.write(line[:-1]+'\r\n') 

Bạn có thể sử dụng dễ dàng trong vòng lặp để chuyển đổi danh sách tệp.