Как определить кодировку текста?

Я получил текст, который закодирован, но я не знаю, какая кодировка была использована. Есть ли способ определить кодировку текстового файла с помощью Python? Как я могу определить кодировку/кодовую страницу текстового файла, связанную с С#.

Ответ 1

Правильное обнаружение кодирования всех времен невозможно.

(Из раздела FAQ:)

Однако некоторые кодировки оптимизированы для определенных языков и языков не являются случайными. Некоторые персонажи последовательности всплывают все время, пока другие последовательности не имеют смысла. человек, свободно владеющий английским языком, который открывает газета и находит "txzqJv 2! dasd0a QqdKjvz" сразу узнает, что это не английский (хотя это составленный полностью из английских букв). Изучая множество "типичных" текстов, компьютерный алгоритм может имитировать этот беглость и образование догадаться о текстовом языке.

Существует библиотека chardet, которая использует это исследование, чтобы попытаться обнаружить кодировку. chardet - это порт кода автоматического обнаружения в Mozilla.

Вы также можете использовать UnicodeDammit. Он попробует следующие методы:

  • Кодировка, обнаруженная в самом документе: например, в декларации XML или (для HTML-документов) тег META-http-equiv. Если Beautiful Soup находит этот вид кодировки внутри документа, он снова анализирует документ с самого начала и дает новую кодировку. Единственное исключение - если вы явно указали кодировку, и эта кодировка действительно сработала: тогда она будет игнорировать любую кодировку, найденную в документе.
  • Кодирование фыркнуло, просмотрев первые несколько байтов файла. Если на этом этапе обнаружено кодирование, оно будет одним из кодировок UTF- *, EBCDIC или ASCII.
  • Кодировка, обнюхаемая библиотекой chardet, если она установлена.
  • UTF-8
  • Windows-1252

Ответ 2

Другой вариант для работы с кодировкой - использовать libmagic (код, стоящий за командой file). Существует множество доступных привязок Python.

Привязки python, которые находятся в дереве исходных файлов, доступны в виде пакета debian python-magic (или python3-magic). Он может определить кодировку файла, выполнив:

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

На pypi есть пакет с pip -магическим pip с одинаковым именем, но несовместимый, который также использует libmagic. Он также может получить кодировку, выполнив:

import magic

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

Ответ 3

Некоторые стратегии кодирования, пожалуйста, раскомментируйте:

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

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

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              

Ответ 4

Вот пример чтения и взятия при значении a chardet предсказания кодирования, считывая n_lines из файла в том случае, если он большой.

chardet также дает вам вероятность (т.е. confidence) его предсказания кодирования (не посмотрел, как они это выходят), который возвращается с его предсказанием из chardet.predict(), поэтому вы можете работать в чем-то, если хотите.

def predict_encoding(file_path, n_lines=20):
    '''Predict a file 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']

Ответ 5

# 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()

Ответ 6

В принципе, невозможно определить кодировку текстового файла в общем случае. Нет, нет стандартной библиотеки Python для этого.

Если у вас есть более конкретные знания о текстовом файле (например, это XML), могут быть библиотечные функции.

Ответ 7

Если вы знаете какое-то содержимое файла, вы можете попробовать его декодировать с несколькими кодировками и посмотреть, что отсутствует. В общем, нет никакого способа, поскольку текстовый файл является текстовым файлом, и это глупо;)

Ответ 8

В зависимости от вашей платформы я просто предпочитаю использовать команду linux shell file. Это работает для меня, так как я использую его в script, который работает исключительно на одной из наших Linux-машин.

Очевидно, что это не идеальное решение или ответ, но оно может быть изменено в соответствии с вашими потребностями. В моем случае мне просто нужно определить, является ли файл UTF-8 или нет.

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

Ответ 9

На этом сайте есть код Python для распознавания ascii, кодирования с помощью boms и utf8 без bom: https://unicodebook.readthedocs.io/guess_encoding.html. Считайте файл в байтовый массив (данные): http://www.codecodex.com/wiki/Read_a_file_into_a_byte_array. Вот пример. Я в оссе.

#!/usr/bin/python                                                                                                  

import sys

def isUTF8(data):
    try:
        decoded = data.decode('UTF-8')
    except UnicodeDecodeError:
        return False
    else:
        for ch in decoded:
            if 0xD800 <= ord(ch) <= 0xDFFF:
                return False
        return True

def get_bytes_from_file(filename):
    return open(filename, "rb").read()

filename = sys.argv[1]
data = get_bytes_from_file(filename)
result = isUTF8(data)
print(result)


PS /Users/js> ./isutf8.py hi.txt                                                                                     
True