Ответ 1
Общий подход к этой проблеме, считывая текстовый файл в обратном порядке, по-разному, может быть решен, по крайней мере, тремя способами.
Общая проблема заключается в том, что, поскольку каждая строка может иметь разную длину, вы не можете заранее знать, где каждая строка начинается в файле, а также сколько из них есть. Это означает, что вам нужно применить некоторую логику к проблеме.
Общий подход # 1: чтение всего файла в память
При таком подходе вы просто читаете весь файл в памяти, в некоторой структуре данных, которая впоследствии позволяет обрабатывать список строк в обратном порядке. Это может быть стек, двусвязный список или даже массив.
Плюсы: Действительно легко реализовать (возможно, встроенный в Python для всех, кого я знаю)
Минусы: Использует много памяти, может потребоваться некоторое время для чтения больших файлов
Общий подход # 2: Прочитайте весь файл, сохраните позицию строк
При таком подходе вы также читаете весь файл один раз, но вместо хранения всего файла (всего текста) в памяти вы сохраняете только двоичные позиции внутри файла, где начиналась каждая строка. Вы можете сохранить эти позиции в аналогичной структуре данных, как та, которая хранит строки в первом подходе.
Вы хотите прочитать строку X, вам нужно перечитать строку из файла, начиная с позиции, которую вы сохранили для начала этой строки.
Плюсы: Почти так же легко реализовать как первый подход
Минусы: может потребоваться некоторое время для чтения больших файлов
Общий подход №3: Прочтите файл в обратном порядке и "выберите его"
При таком подходе вы будете читать фрагмент файла или аналогичный, с конца, и посмотреть, где находятся концы. У вас в основном есть буфер, скажем, 4096 байт, и обрабатывать последнюю строку этого буфера. Когда ваша обработка, которая должна перемещать одну строку за раз назад в этом буфере, подходит к началу буфера, вам нужно прочитать другую ценность данных в буфере, от области до первого прочитанного буфера и продолжить обработку.
Этот подход, как правило, более сложный, потому что вам нужно обрабатывать такие вещи, как линии, разбитые на два буфера, а длинные строки могут даже охватывать более двух буферов.
Это, однако, тот, который потребует наименьшего объема памяти и для действительно больших файлов, также может быть полезно сделать это, чтобы сначала не считывать гигабайты информации.
Плюсы: Использует небольшую память, не требует, чтобы вы сначала прочитали весь файл
Минусы: Многое трудно реализовать и получить право на все угловые случаи
В сети есть множество ссылок, в которых показано, как сделать третий подход: