Использование Chardet для поиска кодировки очень большого файла

Я пытаюсь использовать Chardet выводить кодировку очень большого файла (>4 миллионов строк) в формате с разделителями табуляции.

На данный момент мой сценарий, вероятно, из-за размера файла. Я хотел бы сузить его до загрузки первого x числа строк файла, но у меня возникают трудности при попытке использовать readline(),

Сценарий в его нынешнем виде:

import chardet
import os
filepath = os.path.join(r"O:\Song Pop\01 Originals\2017\FreshPlanet_SongPop_0517.txt")
rawdata = open(filepath, 'rb').readline()


print(rawdata)
result = chardet.detect(rawdata)
print(result)

Это работает, но он читает только первую строку файла. Моя попытка использовать простые циклы для вызова readline() не раз работал не так хорошо (возможно, тот факт, что скрипт открывает файл в двоичном формате).

Выход в одну строку {'encoding': 'Windows-1252', 'confidence': 0.73, 'language': ''}

Мне было интересно, увеличит ли число прочитанных строк доверие к кодированию.

Любая помощь будет принята с благодарностью.

5 ответов

Решение

Я отнюдь не особенно опытен с Чарде, но наткнулся на этот пост, когда отлаживал собственную проблему, и был удивлен, что на него не было никаких ответов. Извините, если это слишком поздно, чтобы быть полезным для ФП, но для всех, кто сталкивается с этим:

Я не уверен, улучшит ли чтение в большей части файла предполагаемый тип кодировки, но все, что вам нужно сделать, чтобы проверить это, будет:

import chardet
testStr = b''
count = 0
with open('Huge File!', 'rb') as x:
    line = x.readline()
    while line and count < 50:  #Set based on lines you'd want to check
        testStr = testStr + line
        count = count + 1
        line = x.readline()
print(chardet.detect(testStr))

В моем случае у меня был файл, который, как мне казалось, имел несколько форматов кодирования, и написал следующее, чтобы проверить его "построчно".

import chardet
with open('Huge File!', 'rb') as x:
line = x.readline()
curChar = chardet.detect(line)
print(curChar)
while line:
    if curChar != chardet.detect(line):
        curChar = chardet.detect(line)
        print(curChar)
    line = x.readline()

Еще один пример с UniversalDetector:

#!/usr/bin/env python
from chardet.universaldetector import UniversalDetector


def detect_encode(file):
    detector = UniversalDetector()
    detector.reset()
    with open(file, 'rb') as f:
        for row in f:
            detector.feed(row)
            if detector.done: break

    detector.close()
    return detector.result

if __name__ == '__main__':
    print(detect_encode('example_file.csv'))

Перерывы, когда доверие = 1,0 . Полезно для очень больших файлов.

Другой пример с chardet

      import chardet


def classify(
    file_path,
    number_of_lines_to_test=1000,
):
    with open(file_path, 'rb') as _file:
        count = 0
        test_string = b''
        while line := _file.readline():
            if count > number_of_lines_to_test:
                break
            test_string += line
            count += 1
    return chardet.detect(test_string)['encoding']

К сожалению, Шарде слишком медленный. Использование выборки строк может привести к ложным срабатываниям.

Лучшая замена Chardet, которую я нашел, — это lib charset-normalizer . Он имеет быструю замену обнаружению Шарде, но также обеспечивает другой подход: лучшая кодировка — та, которая работает. Мигрировать легко, и кажется, что это лучший подход.

      import chardet

with open(filepath, 'rb') as rawdata:
    result = chardet.detect(rawdata.read(100000))
result
Другие вопросы по тегам