Использование 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