Как преобразовать файл в utf-8 в Python?

Мне нужно преобразовать кучу файлов в UTF-8 в Python, и у меня проблемы с частью «преобразование файла».

Я хотел бы сделать эквивалент:

iconv -t utf-8 $file > converted/$file # this is shell code

Спасибо!

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
62
0
113 922
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

Вы можете использовать модуль кодеков, например:

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)

РЕДАКТИРОВАТЬ: добавлен параметр BLOCKSIZE для управления размером блока файла.

read () всегда будет читать весь файл - вы, вероятно, захотите .read (BLOCKSIZE), где BLOCKSIZE - подходящее количество для чтения / записи сразу.

Brian 10.10.2008 18:21

Это сработало для меня в небольшом тесте:

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

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

Еще лучше было бы указать двоичный режим.

Arafangion 12.04.2011 04:10

@Arafangion Почему двоичный режим лучше? Спасибо!

Honghe.Wu 20.02.2014 18:39

@ Honghe.Wu: В Windows по умолчанию используется текстовый режим, а это означает, что окончания строк будут искажены операционной системой, чего вам не нужно, если вы не уверены в кодировке на диске.

Arafangion 30.04.2014 06:59

@Arafangion Как бы выглядел пример, если бы я хотел указать двоичный режим? target = open("target", "wb") есть еще изменения?

The Bndr 23.03.2015 19:32

Спасибо за ответы, работает!

И поскольку исходные файлы находятся в смешанных форматах, я добавил список исходных форматов, которые нужно попробовать последовательно (sourceFormats), а на UnicodeDecodeError я пробую следующий формат:

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
# ...

(РЕДАКТИРОВАТЬ Рудро Бадхон: это включает исходные попытки нескольких форматов, пока вы не получите исключение, а также альтернативный подход, который использует chardet.universaldetector)

В сложных случаях вы можете попытаться обнаружить кодировку с помощью модуля chardet с feedparser.org, но в вашем случае это излишество.

itsadok 13.10.2008 11:17

Мой Python 3.5 не распознает функцию file. Откуда это взялось?

physicalattraction 26.10.2016 11:24

Да, этот ответ был опубликован 8 лет назад, так что это кусок старого кода Python 2.

Sébastien RoccaSerra 26.10.2016 18:42

Чтобы угадать исходную кодировку, вы можете использовать команду file * nix.

Пример:

$ file --mime jumper.xml

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

Это не отвечает на вопрос.

Arthur Julião 17.01.2017 21:50

Это функция Python3 для преобразования любого текстового файла в файл с кодировкой UTF-8. (без использования ненужных пакетов)

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')

Вы можете легко использовать его в цикле для преобразования списка файлов.

это отлично сработало для преобразования из is0-8859-1 в utf-8!

beep_check 27.04.2020 17:04

Это мой метод грубой силы. Он также заботится о смешанных \ n и \ r \ n во входных данных.

    # open the CSV file
    inputfile = open(filelocation, 'rb')
    outputfile = open(outputfilelocation, 'w', encoding='utf-8')
    for line in inputfile:
        if line[-2:] == b'\r\n' or line[-2:] == b'\n\r':
            output = line[:-2].decode('utf-8', 'replace') + '\n'
        elif line[-1:] == b'\r' or line[-1:] == b'\n':
            output = line[:-1].decode('utf-8', 'replace') + '\n'
        else:
            output = line.decode('utf-8', 'replace') + '\n'
        outputfile.write(output)
    outputfile.close()
except BaseException as error:
    cfg.log(self.outf, "Error(18): opening CSV-file " + filelocation + " failed: " + str(error))
    self.loadedwitherrors = 1
    return ([])
try:
    # open the CSV-file of this source table
    csvreader = csv.reader(open(outputfilelocation, "rU"), delimiter=delimitervalue, quoting=quotevalue, dialect=csv.excel_tab)
except BaseException as error:
    cfg.log(self.outf, "Error(19): reading CSV-file " + filelocation + " failed: " + str(error))

Ответ для неизвестный исходный тип кодировки

на основе @ Sébastien RoccaSerra

python3.6

import os    
from chardet import detect

# get file encoding type
def get_encoding_type(file):
    with open(file, 'rb') as f:
        rawdata = f.read()
    return detect(rawdata)['encoding']

from_codec = get_encoding_type(srcfile)

# add try: except block for reliability
try: 
    with open(srcfile, 'r', encoding=from_codec) as f, open(trgfile, 'w', encoding='utf-8') as e:
        text = f.read() # for small files, for big use chunks
        e.write(text)

    os.remove(srcfile) # remove old encoding file
    os.rename(trgfile, srcfile) # rename new encoding
except UnicodeDecodeError:
    print('Decode Error')
except UnicodeEncodeError:
    print('Encode Error')

Другие вопросы по теме