





Вы можете использовать модуль кодеков, например:
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 для управления размером блока файла.
Это сработало для меня в небольшом тесте:
sourceEncoding = "iso-8859-1"
targetEncoding = "utf-8"
source = open("source")
target = open("target", "w")
target.write(unicode(source.read(), sourceEncoding).encode(targetEncoding))
Еще лучше было бы указать двоичный режим.
@Arafangion Почему двоичный режим лучше? Спасибо!
@ Honghe.Wu: В Windows по умолчанию используется текстовый режим, а это означает, что окончания строк будут искажены операционной системой, чего вам не нужно, если вы не уверены в кодировке на диске.
@Arafangion Как бы выглядел пример, если бы я хотел указать двоичный режим? target = open("target", "wb") есть еще изменения?
Спасибо за ответы, работает!
И поскольку исходные файлы находятся в смешанных форматах, я добавил список исходных форматов, которые нужно попробовать последовательно (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, но в вашем случае это излишество.
Мой Python 3.5 не распознает функцию file. Откуда это взялось?
Да, этот ответ был опубликован 8 лет назад, так что это кусок старого кода Python 2.
Чтобы угадать исходную кодировку, вы можете использовать команду file * nix.
Пример:
$ file --mime jumper.xml
jumper.xml: application/xml; charset=utf-8
Это не отвечает на вопрос.
Это функция 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!
Это мой метод грубой силы. Он также заботится о смешанных \ 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')
read () всегда будет читать весь файл - вы, вероятно, захотите .read (BLOCKSIZE), где BLOCKSIZE - подходящее количество для чтения / записи сразу.