Можно ли искать и рассказывать о работе с документами в кодировке UTF-8 на Python?

StackOverflow https://stackoverflow.com/questions/1510188

  •  19-09-2019
  •  | 
  •  

Вопрос

У меня есть приложение, которое генерирует большие файлы журналов размером > 500 МБ.

Я написал несколько утилит на Python, которые позволяют мне быстро просматривать файл журнала и находить интересующие данные.Но теперь я получаю некоторые наборы данных, в которых файл слишком велик, чтобы загрузить его все в память.

Таким образом, я хочу один раз отсканировать документ, построить индекс, а затем загрузить в память только тот раздел документа, который хочу просмотреть за раз.

Это работает для меня, когда я открываю «файл», читаю его по одной строке и сохраняю смещение с помощью file.tell().Затем я могу вернуться к этому разделу файла позже с помощью file.seek( offset, 0 ).

Однако моя проблема в том, что в файлах журналов может быть UTF-8, поэтому мне нужно открыть их с помощью модуля кодеков (codecs.open(<filename>, 'r', 'utf-8')).С помощью полученного объекта я могу вызвать поиск и сказать, но они не совпадают.

Я предполагаю, что кодекам необходимо выполнить некоторую буферизацию или, может быть, они возвращают количество символов вместо байтов из сообщения?

Есть ли способ обойти это?

Это было полезно?

Решение

Если это правда, это похоже на ошибку или ограничение модуля кодеков, поскольку он, вероятно, путает смещения байтов и символов.

я бы использовал обычный open() функция открытия файла, затем seek()/tell() даст вам смещения байтов, которые всегда согласованы.Всякий раз, когда вы хотите прочитать, используйте f.readline().decode('utf-8').

Однако помните, что использование f.read() функция может поместить вас в середину многобайтового символа, что приведет к ошибке декодирования UTF-8. readline() всегда будет работать.

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

Другие советы

Для UTF-8 вам фактически не нужно открывать файл с помощью codecs.open.Вместо этого можно сначала прочитать файл как байтовую строку, а затем декодировать отдельный раздел (вызывая метод .decode для строки).Разрыв файла по границам строк безопасен;единственный небезопасный способ разделить его — посередине многобайтового символа (который вы можете распознать по значению его байта> 128).

Многое из того, что происходит с UTF8 в Python, имеет смысл, если вы посмотрите, как это было сделано в Python 3.В вашем случае это будет иметь больше смысла, если вы прочитаете главу «Файлы» в книге «Погружение в Python 3»: http://diveintopython3.org/files.html

Короче говоря, это то, что file.seek и file.tell работать с позициями байтов, тогда как символы Юникода могут занимать несколько байтов.Таким образом, если вы это сделаете:

f.seek(10)
f.read(1)
f.tell()

Вы можете легко получить что-то кроме 17, в зависимости от длины прочитанного символа.

Обновлять:Вы не можете выполнять поиск/сообщение об объекте, возвращаемом codec.open().Вам нужно использовать обычный файл и после прочтения декодировать строки в Юникод.

Я не знаю, почему это не работает, но я не могу заставить это работать.Например, кажется, что поиск срабатывает только один раз.Затем вам нужно закрыть и снова открыть файл, что, конечно, бесполезно.

Сообщение не использует позиции символов, но не показывает, где находится ваша позиция в потоке (но, вероятно, где находится базовый файловый объект при чтении с диска).

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top