У меня есть текстовый файл, который содержит метку времени на каждой строке. Моя цель состоит в том, чтобы найти диапазон времени. Все времена в порядке, таким образом, первая строка будет самым ранним временем, и последняя строка будет последним временем. Мне только нужна самая первая и самая последняя строка. Каков был бы самый эффективный способ получить эти строки в Python?
Примечание: Эти файлы являются относительно большими в длине, приблизительно 1-2 миллиона строк каждый, и я должен сделать это для нескольких сотен файлов.
with open(fname, 'rb') as fh:
first = next(fh).decode()
fh.seek(-1024, 2)
last = fh.readlines()[-1].decode()
Значение переменной здесь 1024: она представляет собой среднюю длину строки. Я выбираю 1024 только для примера. Если у вас есть оценка средней длины строки, вы можете просто использовать это значение, умноженное на 2.
Поскольку вы понятия не имеете о возможной верхней границе длины строки, очевидным решением будет перебор файла:
for line in fh:
pass
last = line
Вам не нужно возиться с двоичным флагом, вы можете просто использовать open(fname)
.
ETA: Поскольку у вас много файлов для работы, вы можете создать выборку из нескольких десятков файлов с помощью random.sample
и запустить на них этот код для определения длины последней строки. С априорно большим значением позиционного сдвига (скажем, 1 МБ). Это поможет вам оценить значение для полного прогона.
Можете ли вы использовать команды unix? Я думаю, что использование head -1
и tail -n 1
, вероятно, наиболее эффективные методы. В качестве альтернативы можно использовать простой fid.readline()
для получения первой строки и fid.readlines()[-1]
, но это может занять слишком много памяти.
Получить первую строку тривиально просто. Для последней строки, предполагая, что вы знаете приблизительную верхнюю границу длины строки, os.lseek некоторая сумма из SEEK_END
найти предпоследнюю строку, заканчивающуюся, а затем readline ( ) последняя строка.
Вот модифицированная версия ответа SilentGhost, которая сделает то, что вы хотите.
with open(fname, 'rb') as fh:
first = next(fh)
offs = -100
while True:
fh.seek(offs, 2)
lines = fh.readlines()
if len(lines)>1:
last = lines[-1]
break
offs *= 2
print first
print last
Здесь не нужна верхняя граница для длины строки.