В семействе операционных систем Linux существует одна прекрасная консольная утилита — tail
. Она предназначена для случаев, когда нам не нужно читать весь файл, а достаточно просмотреть только несколько последних строк.
Напишите аналог этой утилиты.
Формат ввода
Пользователь вводит имя файла (F), а затем количество строк (N), которые он хочет увидеть.
Формат вывода
Выведите N последних строк файла F.
Пример
Ввод
# Пользовательский ввод:
some_file.txt
2
# Содержимое файла some_file.txt
1 строка
2 строка
3 строка
4 строка
5 строка
Вывод
4 строка
5 строка
Решение
Если вспомнить, что можно воспользоваться срезами, то задача решается элементарно.
Считываем файл любым удобным для нас способом и построчно помещаем его в список. С помощью среза обираем последние N строчек (последние N элементов) и выводим их.
Посмотреть код
Решение
Python
file_name = input().strip()
lines = int(input())
with open(file_name, encoding='UTF-8') as file:
data = [string for string in file.read().split('\n') if string]
# или так
# data = file.read().rstrip().split('\n')
print('\n'.join(data[-lines:]))
Решение
Python
file_name = input()
lines = int(input())
data = []
with open(file_name) as file:
for string in file:
data.append(string)
for string in data[-lines:]:
print(string.strip())
скажите, пожалуйста, возможно ли написать кд для следующего способа решения??
я не хочу сохранять все строки в список
могу ли я посчитать количество строк?
могу ли я начать вывод строки в нужны момент?
я попытался сделать следующее:
with open(file_in, ‘r’, encoding=”UTF-8″) as file_in:
line_count = sum(1 for line in file_in)
for line in file_in.readlines():
lines.append(line.strip())
Как я понял второй раз по файлу второй цикл for не стал проходить.
Я пока что что не гуглил способ решения задачи
Скажите, пожалуйста, имеет ли смысл искать ответ?
На мой взгляд, существует всего два основных способа решения задачи: в один проход с техникой “скользящего окна” когда вы держите в памяти нужное количество последних строк и выводите их когда достигаете конца файла, и двойное чтение файла, когда вы читаете файл и считаете количество строк, а потом читаете снова и выводите начиная с нужной строки.
Вы реализуете второй способ, но проблема вашего решения в том, что для того, чтобы сработал второй цикл, нужно “переоткрыть” файл. Дело в том, что в этой модели чтения файлов есть так называемая каретка (указатель) по аналогии с пишущей машинкой и по-умолчанию она идет только вперед. Когда вы считаете количество строк и доходите до конца файла каретка остается там. Соотвественно циклу уже нечего читать в файле.
Пока писал, подумал, что есть еще один – продвинутый, если читать файл с конца и считать количество знаков “перевод строки”, а в нужный момент, когда это количество превысило необходимое число “разворачиваться” и читать его в правильном порядке. Наверное это самый эффективный способ для огромных файлов, но он сложнее других в реализации. Конечно, чтобы он работал быстро и хорошо, читать надо не посимвольно а относительно большими блоками, скажем, по десяткам килобайт.
спасибо большое))
и за объяснение
и за варианты
и за продвинутый
тяжело увидеть различие на таких примерах, но теперь есть знание об алгоритме
Привел такое решение. Причем в PyCharm выводит как надо: 4 строка \n 5 строка, а в решении Яндекса только: 5 строка. не могли бы прокомментировать в чем ошибка. и попутный вопрос: считывание из файла строк в генератор делается только для того, чтобы не перегружать память?
with open(input(), encoding=“UTF-8”) as file_in:
lines = file_in.read().split(‘\n’)
print(*lines[-int(input()):], sep=‘\n’)
Ключевая разница наших решений как раз затрагивает ваш вопрос – почему именно так:
Дело в том, что наш файл заканчивается переводом строки и поэтому ваша конструкция lines = file_in.read().split(‘\n’) дает лишний пустой элемент в конце. Решить проблему можно обрезав последний перевод строки
но это решение, как и первое приведенное мною будет “подгонкой” под конкретные данные.
Проблема этой задачи заключается в том, что мы не знаем что делать с пустыми строками. В теории в логах их быть не должно, поэтому я их просто выкидываю, но не факт, что это правильное поведение.
Второе решение показывает и считает все “как есть” и по этой причине не имеет проблемы ни с ‘\n’ в конце строки, ни с пустыми строками.
Да, я тоже в процессе рассуждения (после опубликованного комментария) пришла к тому, что дело в пустой строке. Спасибо за оперативный ответ!