2008-10-10 35 views

Respuesta

44

Puede utilizar el codecs module, así:

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) 

EDITAR: BLOCKSIZE añadió parámetro para controlar el tamaño del trozo de archivos.

+3

read() leerá siempre el archivo completo; probablemente desee .read (BLOCKSIZE), donde BLOCKSIZE es una cantidad adecuada para leer/escribir a la vez. – Brian

+1

Eso es cierto, gracias. Voy a modificar mi ejemplo. – DzinX

25

Esto funcionó para mí en una pequeña prueba:

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

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

Aún mejor sería especificar el modo binario. – Arafangion

+0

@Arafangion ¿Por qué el modo binario sería mejor? ¡Gracias! –

+0

@ Honghe.Wu: en Windows, el modo de texto es el predeterminado, y eso significa que las terminaciones de línea serán destruidas por el sistema operativo, algo que no desea si no está seguro acerca de la codificación en el disco. – Arafangion

12

Gracias por las respuestas, funciona!

Y puesto que los archivos de origen están en formatos mixtos, he añadido una lista de formatos de origen para ser juzgados en secuencia (sourceFormats), y en UnicodeDecodeError que pruebe con el siguiente formato:

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 Rudro Badhon: esto incorpora el intento original de múltiples formatos hasta que no obtenga una excepción, así como un enfoque alternativo que usa el detector de tipo chardet.universal)

+0

Para casos difíciles, puede intentar detectar la codificación con el módulo chardet de feedparser.org, pero en su caso es una exageración. – itsadok

+0

My Python 3.5 no reconoce la función 'archivo'. De donde viene eso? – physicalattraction

+0

Sí, esta respuesta se publicó hace 8 años, por lo que es una pieza del antiguo código de Python 2. –

0

Para adivinar cuál es la fuente de codificación, puede usar el comando file * nix.

Ejemplo:

$ file --mime jumper.xml 

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

No responde la pregunta. –

0

Este es un función python3 para convertir cualquier archivo de texto en el uno con codificación UTF-8. (sin usar paquetes innecesarios)

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

Puede usarlo fácilmente en un bucle para convertir una lista de archivos.

Cuestiones relacionadas