open - python encode utf8
Determine la codificación de texto en Python (8)
Recibí un texto que está codificado, pero no sé qué juego de caracteres se utilizó. ¿Hay alguna manera de determinar la codificación de un archivo de texto usando Python? ¿Cómo puedo detectar la codificación / página de códigos de un archivo de texto con C #?
Algunas estrategias de codificación, por favor, descomentar a gusto:
#!/bin/bash
#
tmpfile=$1
echo ''-- info about file file ........''
file -i $tmpfile
enca -g $tmpfile
echo ''recoding ........''
#iconv -f iso-8859-2 -t utf-8 back_test.xml > $tmpfile
#enca -x utf-8 $tmpfile
#enca -g $tmpfile
recode CP1250..UTF-8 $tmpfile
Es posible que desee comprobar la codificación abriendo y leyendo el archivo en forma de bucle ... pero es posible que deba verificar primero el tamaño del archivo:
encodings = [''utf-8'', ''windows-1250'', ''windows-1252'' ...etc]
for e in encodings:
try:
fh = codecs.open(''file.txt'', ''r'', encoding=e)
fh.readlines()
fh.seek(0)
except UnicodeDecodeError:
print(''got unicode error with %s , trying different encoding'' % e)
else:
print(''opening the file with encoding: %s '' % e)
break
Aquí hay un ejemplo de chardet
leer y tomar al chardet
una predicción de codificación de chardet
, leyendo n_lines
del archivo en caso de que sea grande.
chardet
también le da una probabilidad (es decir, confidence
) de su predicción de codificación (no se ha buscado cómo se le ocurre), que se devuelve con su predicción de chardet.predict()
, por lo que podría trabajar de alguna manera si lo desea .
def predict_encoding(file_path, n_lines=20):
''''''Predict a file''s encoding using chardet''''''
import chardet
# Open the file as binary data
with open(file_path, ''rb'') as f:
# Join binary lines for specified number of lines
rawdata = b''''.join([f.readline() for _ in range(n_lines)])
return chardet.detect(rawdata)[''encoding'']
Dependiendo de su plataforma, simplemente opto por usar el comando linux shell file
. Esto funciona para mí ya que lo estoy usando en un script que se ejecuta exclusivamente en una de nuestras máquinas Linux.
Obviamente, esta no es una solución o respuesta ideal, pero podría modificarse para satisfacer sus necesidades. En mi caso, solo necesito determinar si un archivo es UTF-8 o no.
import subprocess
file_cmd = [''file'', ''test.txt'']
p = subprocess.Popen(file_cmd, stdout=subprocess.PIPE)
cmd_output = p.stdout.readlines()
# x will begin with the file type output as is observed using ''file'' command
x = cmd_output[0].split(": ")[1]
return x.startswith(''UTF-8'')
Detectar correctamente la codificación todo el tiempo es imposible .
(De las preguntas frecuentes de chardet :)
Sin embargo, algunas codificaciones están optimizadas para idiomas específicos y los idiomas no son aleatorios. Algunas secuencias de caracteres aparecen todo el tiempo, mientras que otras secuencias no tienen sentido. Una persona con fluidez en inglés que abre un periódico y encuentra "txzqJv 2! Dasd0a QqdKjvz" reconocerá al instante que no es inglés (a pesar de que está compuesto completamente de letras en inglés). Al estudiar muchos textos "típicos", un algoritmo de computadora puede simular este tipo de fluidez y hacer una conjetura sobre el lenguaje de un texto.
Existe la biblioteca chardet que usa ese estudio para tratar de detectar la codificación. chardet es un puerto del código de autodetección en Mozilla.
También puedes usar UnicodeDammit . Probará los siguientes métodos:
- Una codificación descubierta en el documento en sí: por ejemplo, en una declaración XML o (para documentos HTML) una etiqueta META de http-equiv. Si Beautiful Soup encuentra este tipo de codificación dentro del documento, vuelve a analizar el documento desde el principio y prueba la nueva codificación. La única excepción es si especificó explícitamente una codificación, y esa codificación realmente funcionó: entonces ignorará cualquier codificación que encuentre en el documento.
- Una codificación olfateó al mirar los primeros bytes del archivo. Si se detecta una codificación en esta etapa, será una de las codificaciones UTF- *, EBCDIC o ASCII.
- Una codificación olfateada por la biblioteca chardet , si la tienes instalada.
- UTF-8
- Windows-1252
En principio, es imposible determinar la codificación de un archivo de texto, en el caso general. Entonces no, no hay una biblioteca de Python estándar para hacer eso por usted.
Si tiene un conocimiento más específico sobre el archivo de texto (por ejemplo, que es XML), puede haber funciones de biblioteca.
Otra opción para calcular la codificación es usar libmagic (que es el código detrás del comando de file ). Hay una profusión de enlaces de pitón disponibles.
Las vinculaciones de python que viven en el árbol fuente de archivos están disponibles como el paquete Debian de python-magic (o python3-magic ). Si puede determinar la codificación de un archivo, haga lo siguiente:
import magic
blob = open(''unknown-file'').read()
m = magic.open(magic.MAGIC_MIME_ENCODING)
m.load()
encoding = m.buffer(blob) # "utf-8" "us-ascii" etc
Hay un paquete de pipi python-magic llamado idéntico, pero incompatible, en pypi que también usa libmagic. También puede obtener la codificación, haciendo:
import magic
blob = open(''unknown-file'').read()
m = magic.Magic(mime_encoding=True)
encoding = m.from_buffer(blob)
Si conoce el contenido del archivo, puede intentar descifrarlo con varias codificaciones y ver cuál falta. En general, no hay forma, ya que un archivo de texto es un archivo de texto y esos son estúpidos;)
# Function: OpenRead(file)
# A text file can be encoded using:
# (1) The default operating system code page, Or
# (2) utf8 with a BOM header
#
# If a text file is encoded with utf8, and does not have a BOM header,
# the user can manually add a BOM header to the text file
# using a text editor such as notepad++, and rerun the python script,
# otherwise the file is read as a codepage file with the
# invalid codepage characters removed
import sys
if int(sys.version[0]) != 3:
print(''Aborted: Python 3.x required'')
sys.exit(1)
def bomType(file):
"""
returns file encoding string for open() function
EXAMPLE:
bom = bomtype(file)
open(file, encoding=bom, errors=''ignore'')
"""
f = open(file, ''rb'')
b = f.read(4)
f.close()
if (b[0:3] == b''/xef/xbb/xbf''):
return "utf8"
# Python automatically detects endianess if utf-16 bom is present
# write endianess generally determined by endianess of CPU
if ((b[0:2] == b''/xfe/xff'') or (b[0:2] == b''/xff/xfe'')):
return "utf16"
if ((b[0:5] == b''/xfe/xff/x00/x00'')
or (b[0:5] == b''/x00/x00/xff/xfe'')):
return "utf32"
# If BOM is not provided, then assume its the codepage
# used by your operating system
return "cp1252"
# For the United States its: cp1252
def OpenRead(file):
bom = bomType(file)
return open(file, ''r'', encoding=bom, errors=''ignore'')
#######################
# Testing it
#######################
fout = open("myfile1.txt", "w", encoding="cp1252")
fout.write("* hi there (cp1252)")
fout.close()
fout = open("myfile2.txt", "w", encoding="utf8")
fout.write("/u2022 hi there (utf8)")
fout.close()
# this case is still treated like codepage cp1252
# (User responsible for making sure that all utf8 files
# have a BOM header)
fout = open("badboy.txt", "wb")
fout.write(b"hi there. barf(/x81/x8D/x90/x9D)")
fout.close()
# Read Example file with Bom Detection
fin = OpenRead("myfile1.txt")
L = fin.readline()
print(L)
fin.close()
# Read Example file with Bom Detection
fin = OpenRead("myfile2.txt")
L =fin.readline()
print(L) #requires QtConsole to view, Cmd.exe is cp1252
fin.close()
# Read CP1252 with a few undefined chars without barfing
fin = OpenRead("badboy.txt")
L =fin.readline()
print(L)
fin.close()
# Check that bad characters are still in badboy codepage file
fin = open("badboy.txt", "rb")
fin.read(20)
fin.close()