it-swarm.com.de

Wie bestimme ich die Kodierung von Text?

Ich habe einen Text erhalten, der verschlüsselt ist, aber ich weiß nicht, welcher Zeichensatz verwendet wurde. Gibt es eine Möglichkeit, die Kodierung einer Textdatei mit Python zu bestimmen? Wie kann ich die Kodierung/Codepage einer Textdatei erkennen befasst sich mit C #.

166
Nope

Das korrekte Erkennen der Kodierung zu allen Zeiten ist unmöglich.

(Von den chardet FAQ :)

Einige Kodierungen sind jedoch optimiert für bestimmte Sprachen und Sprachen sind nicht zufällig Irgendein Zeichen Sequenzen werden ständig angezeigt, während andere Sequenzen machen keinen Sinn. EIN Englisch fließende Person, die ein .__ öffnet. Zeitung und findet "txzqJv 2! dasd0a QqdKjvz ”erkennt das sofort das ist nicht Englisch (obwohl es nur aus englischen Buchstaben besteht) . Durch das Studium vieler typischer Texte wird ein Computeralgorithmus kann dies simulieren Art fließend und machen einen gebildeten raten Sie über die Sprache eines Textes.

Es gibt die Bibliothek " chardet ", die anhand dieser Studie versucht, die Kodierung zu erkennen. chardet ist ein Port des Codes für die automatische Erkennung in Mozilla. 

Sie können auch UnicodeDammit verwenden. Es werden die folgenden Methoden versucht:

  • Eine Kodierung, die im Dokument selbst entdeckt wurde: beispielsweise in einer XML-Deklaration oder (bei HTML-Dokumenten) einem http-equiv-META-Tag. Wenn Beautiful Soup diese Art von Kodierung im Dokument findet, analysiert es das Dokument erneut und beginnt die neue Kodierung. Die einzige Ausnahme ist, wenn Sie eine Kodierung explizit angegeben haben und diese Kodierung tatsächlich funktioniert hat: Dann werden alle im Dokument gefundenen Kodierungen ignoriert.
  • Eine Codierung, bei der die ersten Bytes der Datei gesichtet wurden. Wenn zu diesem Zeitpunkt eine Codierung erkannt wird, handelt es sich um eine der UTF- * - Codierungen, EBCDIC oder ASCII.
  • Eine von der chardet library geriefte Codierung, falls installiert.
  • UTF-8
  • Windows-1252 
179
nosklo

Eine weitere Möglichkeit, die Kodierung herauszufinden, ist die Verwendung von libmagic (der Code hinter dem Befehl file ). Es gibt eine Fülle von Python-Bindungen.

Die im Quelltextbaum enthaltenen Python-Bindungen sind als python-magic (oder python3-magic ) Debian-Paket verfügbar. Es kann die Kodierung einer Datei bestimmen, indem Sie Folgendes tun:

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

Es gibt ein identisch benanntes, aber inkompatibles python-magic pip-Paket für pypi, das ebenfalls libmagic verwendet. Es kann auch die Kodierung erhalten, indem Sie Folgendes tun:

import magic

blob = open('unknown-file').read()
m = magic.Magic(mime_encoding=True)
encoding = m.from_buffer(blob)
44
Hamish Downer

Einige Kodierungsstrategien, bitte unkommentiert nach Geschmack: 

#!/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

Sie können die Kodierung überprüfen, indem Sie die Datei in Form einer Schleife öffnen und lesen. Möglicherweise müssen Sie jedoch zuerst die Dateigröße überprüfen:

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              
23
zzart

Hier ist ein Beispiel für das Lesen und Nehmen einer chardet-Codierungsvorhersage zum Nennwert, wobei n_lines aus der Datei gelesen wird, falls diese groß ist.

chardet gibt Ihnen auch eine Wahrscheinlichkeit (dh confidence) der Kodierungsvoraussage (haben Sie nicht darauf geachtet, wie sie dazu gekommen sind), die mit ihrer Vorhersage von chardet.predict() zurückgegeben wird, sodass Sie dies irgendwie bearbeiten können, wenn Sie möchten .

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']
12
ryanjdillon
# 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()
1
Bill Moore

Grundsätzlich ist es nicht möglich, die Kodierung einer Textdatei zu bestimmen. Nein, es gibt keine Standard-Python-Bibliothek, die das für Sie erledigt.

Wenn Sie mehr über die Textdatei wissen (z. B. XML), gibt es möglicherweise Bibliotheksfunktionen.

0

Wenn Sie den Inhalt der Datei kennen, können Sie versuchen, sie mit verschiedenen Codierungen zu decodieren und festzustellen, welche fehlen. Im Allgemeinen gibt es keine Möglichkeit, da eine Textdatei eine Textdatei ist und diese dumm sind;)

0
Martin Thurau

Abhängig von Ihrer Plattform entscheide ich mich für den Befehl linux Shell file. Dies funktioniert für mich, da ich es in einem Skript verwende, das ausschließlich auf einem unserer Linux-Maschinen ausgeführt wird.

Offensichtlich ist dies keine ideale Lösung oder Antwort, aber es könnte an Ihre Bedürfnisse angepasst werden. In meinem Fall muss ich nur feststellen, ob eine Datei UTF-8 ist oder nicht.

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