Php прочитать последнюю строку файла

Обновлено: 04.07.2024

У меня есть файл с именем file.txt , который обновляется путем добавления к нему строк.

Я читаю это по этому коду:

И появляется огромное количество строк. Я просто хочу повторить последние 5 строк файла

Как я могу это сделать ?

file.txt выглядит так:

Непроверенный код, но должен работать:

Вызов max обрабатывает файл, содержащий менее 6 строк.

Для большого файла считывание всех строк в массив с помощью file () немного расточительно. Вот как вы можете прочитать файл и сохранить буфер из последних 5 строк:

Вы могли бы немного оптимизировать это с помощью некоторых эвристик о вероятной длине строки, перейдя к позиции, скажем, примерно в 10 строках от конца и вернувшись еще дальше, если это не дает 5 строк. Вот простая реализация, демонстрирующая это:

Если вы работаете в системе Linux, вы можете сделать это:

В противном случае вам придется посчитать строки и взять последние 5, что-то вроде:

Это будет быстро для больших файлов, но много кода для простой задачи, если есть БОЛЬШИЕ ФАЙЛЫ, используйте это

ReadFromEndByLine ('myFile.txt', 6);

Это частый вопрос на собеседовании. Вот что я написал в прошлом году, когда мне задали этот вопрос. Помните, что код, который вы получаете на Stack Overflow, лицензирован Creative Commons Share-Alike с обязательной атрибуцией.

Это решение делает предположение о максимальной длине линии. Интервьюер спросил меня, как бы я решил проблему, если бы я не мог сделать это предположение, и мне пришлось бы использовать строки, которые потенциально были длиннее любой максимальной длины, которую я выбрал.

Я сказал ему, что любой программный проект должен делать определенные предположения, но я могу проверить, было ли $c меньше желаемого количества строк, а если нет, fseek() обратно постепенно (удваивая каждую time), пока у нас не будет достаточно строк.

Открытие больших файлов с помощью file() может привести к созданию большого массива с сохранением значительного объема памяти.

Вы можете уменьшить стоимость памяти с помощью SplFileObject , поскольку он выполняет итерацию по каждой строке.

Используйте метод seek (из seekableiterator ), чтобы получить последнюю строку. Затем вы должны вычесть текущее значение ключа на 5.

Чтобы получить последнюю строку, используйте PHP_INT_MAX . (Да, это обходной путь.)

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

Я считаю, что лучше всего использовать какую-нибудь ОС-утилиту, например, tail в unix.

БЫСТРЫЙ

Вот БЫСТРЫЙ метод для БОЛЬШИХ файлов с НИЗКОЙ стоимостью памяти - я разрабатываю ответ Уоллеса Макстерса (если вы хотите проголосовать - сделайте это на его ответ), обернув его код внутри удобной функции и добавив обратную функцию

При этом не используется file() , поэтому он будет более эффективным для больших файлов;

Функция PHP file () считывает весь файл в массив. Это решение требует наименьшего количества ввода:

Эта функция будет работать для ДЕЙСТВИТЕЛЬНО больших файлов размером менее 4 ГБ. Скорость достигается за счет чтения большого количества данных вместо одного байта за раз и подсчета строк.

После выполнения вышеуказанной функции вы можете просто выполнить fgets () в цикле, чтобы читать каждую строку за раз из $ fh.

Вы можете использовать мою небольшую вспомогательную библиотеку (2 функции)

Примеры сохранения и чтения текстовых данных и массивов в файлы.

Сохранение в файл

Функция file_put_contents() записывает содержимое переменной в файл, если файла не существует. то пытается его создать, если существует то полностью перезапишет его.

File_put_contents:

Fopen / fwrite:

Набор функций fopen, fwrite, fclose предназначены для более гибкой работы с файлами.

  • fopen – открытие или создание файла.
  • fwrite – запись данных.
  • fclose – закрытие файла.

Возможные режимы fopen():

Mode Описание
r Открывает файл только для чтения, помещает указатель в начало файла.
r+ Открывает файл для чтения и записи, помещает указатель в начало файла.
w Открывает файл только для записи, помещает указатель в начало файла и обрезает файл до нулевой длины. Если файл не существует – пробует его создать.
w+ Открывает файл для чтения и записи, помещает указатель в начало файла и обрезает файл до нулевой длины. Если файл не существует – пытается его создать.
a Открывает файл только для записи, помещает указатель в конец файла. Если файл не существует – пытается его создать.
a+ Открывает файл для чтения и записи, помещает указатель в конец файла. Если файл не существует – пытается его создать.
x Создаёт и открывает только для записи; помещает указатель в начало файла. Если файл уже существует, вызов fopen() закончится неудачей, вернёт false и выдаст ошибку. Если файл не существует, попытается его создать.
x+ Создаёт и открывает для чтения и записи, в остальном имеет то же поведение, что и « x ».
c Открывает файл только для записи. Если файл не существует, то он создаётся. Если же файл существует, то он не обрезается (в отличие от « w »), и вызов к этой функции не вызывает ошибку (также как и в случае с « x »). Указатель на файл будет установлен на начало файла.
c+ Открывает файл для чтения и записи, в остальном имеет то же поведение, что и « c ».

Доступно в место fwrite() используют fputs() , разницы ни какой т.к. эта функция является псевдонимом.

Как прочитать только 5 последнюю строку текстового файла в PHP?

Учебное пособие по регулярным выражениям (Regex): как сопоставить любой шаблон текста

У меня есть файл с именем file.txt который обновляется путем добавления к нему строк.

Я читаю это по этому коду:

и появляется огромное количество строк. Я просто хочу повторить последние 5 строк файла

Как я могу это сделать ?

В file.txt вот так:

Непроверенный код, но должен работать:

Вызов max обработает файл менее 6 строк.

  • 5 что если filename.txt содержит только 3 строки?
  • это хорошо, но нужно отметить критические проблемы. то есть $ i может быть меньше 0; так что вам это нужно, если ($ i> 0) echo .
  • 8 Не очень хорошо, так как это зря потребляет много оперативной памяти, если файл журнала большой.
  • 1 Ужасный код с точки зрения использования памяти. Он помещает в память весь файл. Если этот файл будет очень большим, у вас проблемы.

Для большого файла чтение всех строк в массив с помощью file () немного расточительно. Вот как вы можете прочитать файл и сохранить буфер из последних 5 строк:

Вы могли бы немного оптимизировать это с помощью эвристики о вероятной длине строки, перейдя к позиции, скажем, примерно в 10 строках от конца, и вернувшись еще дальше, если это не дает 5 строк. Вот простая реализация, демонстрирующая это:

  • @Paual Dixon, в цикле while вы читаете всю строку и сохраняете последнюю строку X. можно ли прочитать последние X строк?

Если вы работаете в системе Linux, вы можете сделать это:

В противном случае вам придется посчитать строки и взять последние 5, что-то вроде:

Это будет быстро для больших файлов, но много кода для простой задачи, если есть БОЛЬШИЕ ФАЙЛЫ, используйте это

Это общий вопрос на собеседовании. Вот что я написал в прошлом году, когда мне задали этот вопрос. Помните, что код, который вы получаете на Stack Overflow, лицензирован Creative Commons Share-Alike с обязательной ссылкой на источник.

Это решение делает предположение о максимальной длине линии. Интервьюер спросил меня, как бы я решил проблему, если бы не смог сделать это предположение и должен был бы использовать строки, которые потенциально были бы длиннее любой максимальной длины, которую я выбрал.

Я сказал ему, что любой программный проект должен делать определенные предположения, но я могу проверить, $c было меньше желаемого количества строк, а если нет, fseek() обратно постепенно (удваивая каждый раз), пока мы не получим достаточно строк.

  • $data установлен, но никогда не использовался. Вы уверены, что этот фрагмент echo любые совпадающие строки?
  • @mjohns Это было 10 лет назад, но я помню, что тестировал его. Возвращаемое значение fseek () в PHP просто 0 в случае успеха или -1 в случае неудачи. Я согласен, что было бы уместно проверить этот статус.

Открытие больших файлов с помощью file() может создать большой массив, зарезервировав значительный кусок памяти.

Вы можете снизить стоимость памяти с помощью SplFileObject так как он проходит через каждую строку.

Использовать seek метод seekableiterator ), чтобы получить последнюю строку. Затем вы должны вычесть текущее значение ключа на 5.

Чтобы получить последнюю строку, используйте PHP_INT_MAX . (Да, это обходной путь.)

  • 1 Я рекомендую этот быстрый метод для больших файлов

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

Я считаю, что лучше всего использовать какую-нибудь ОС-утилиту, например, tail в unix.

  • $output - это массив, поэтому, если вы повторяете эхо, вам нужно будет использовать implode ()

Это не использует file() так это будет более эффективно для больших файлов;

БЫСТРО

Вот БЫСТРЫЙ метод для БОЛЬШИХ файлов с НИЗКОЙ стоимостью памяти - я разрабатываю ответ Уоллеса Макстерса (если вы хотите проголосовать - сделайте это по его ответу), заключив его код в удобную функцию и добавив обратную функцию

  • 1 Чисто и просто, без лишних классов и методов классов - спасибо.

Функция PHP file () считывает весь файл в массив. Это решение требует наименьшего количества ввода:

Эта функция будет работать для ДЕЙСТВИТЕЛЬНО больших файлов размером менее 4 ГБ. Скорость достигается за счет чтения большого количества данных вместо одного байта за раз и подсчета строк.

После выполнения вышеуказанной функции вы можете просто выполнить fgets () в цикле, чтобы читать каждую строку за раз из $ fh.

Вы можете использовать мою небольшую вспомогательную библиотеку (2 функции)

Тогда просто используйте:

Я это тестировал. Меня устраивает.

The filesize is:'.filesize('$filename'); > getlast('file.txt',6,230); ?> var13 ->

Наименьшее количество баранов и хорошо выводит. Я согласен с Полом Диксоном .

Вот мое решение:

Если ваши строки разделены CR или LF, попробуйте взорвать переменную $ data:

$ lines должны стать массивом, и вы можете вычислить количество записей с помощью sizeof () и просто получить последние 5.

В моем PHP-приложении мне нужно прочитать несколько строк, начиная с конца много файлов (в основном журналы). Иногда мне нужен только последний, иногда мне нужно десятки или сотни. По сути, я хочу что-то такое же гибкое, как Unix tail команда.

Здесь есть вопросы о том, как получить последнюю строчку из файла (но Мне нужно N строк), и были даны разные решения. Я не уверен, о чем один из них самый лучший и лучше работает.

4 ответа

Обзор методов

Выполняя поиск в интернете, я сталкивался с различными решениями. Я могу сгруппировать их в трех подходах:

  • наивные те, которые используют функцию file() PHP;
  • обман те, которые запускают команду tail в системе;
  • могучие , которые с радостью прыгают вокруг открытого файла, используя fseek() .

Я выбрал (или написал) пять решений: наивное , обман . и три могучих .

  1. Самое краткое наивное решение, используя встроенные функции массива.
  2. единственно возможное решение на основе tail команда , которая имеет небольшая большая проблема: он не запускается, если tail недоступно, как на не Unix (Windows) или в ограниченных средах, которые не позволяют системе функции.
  3. Решение, в котором отдельные байты читаются с конца поиска файла для (и подсчета) символов новой строки можно найти здесь.
  4. Найдено решение многобайтовой буферизации , оптимизированное для больших файлов здесь .
  5. Слегка измененная версия решения № 4, в которой длина буфера равна динамический, определяется в соответствии с количеством строк для извлечения.

Все решения работают . В том смысле, что они возвращают ожидаемый результат от любой файл и для любого количества строк, которые мы просим (кроме решения № 1, которое может нарушать ограничения памяти PHP в случае больших файлов, ничего не возвращая). Но какой лучше?

Тесты производительности

Чтобы ответить на вопрос, я запускаю тесты. Вот как это делается, не так ли?

Я подготовил образец файла 100 КБ , который объединяет различные файлы, найденные в мой /var/log каталог. Затем я написал скрипт PHP, который использует каждый из пять решений для извлечения строк 1, 2, . 10, 20, . 100, 200, . 1000 с конца файла. Каждый тест повторяется десять раз (это что-то вроде 5 × 28 × 10 = 1400 (тесты), измерение среднего показателя время в микросекундах.

Я запускаю скрипт на своей локальной машине для разработки (Xubuntu 12.04, PHP 5.3.10, двухъядерный процессор 2,70 ГГц, 2 ГБ ОЗУ) с использованием командной строки PHP переводчик. Вот результаты:

Время выполнения на примере файла журнала объемом 100 КБ

Решения № 1 и № 2 кажутся худшими. Решение № 3 хорошо только тогда, когда нам нужно прочитайте несколько строк. Решения № 4 и № 5 кажутся лучшими. Обратите внимание, как динамический размер буфера может оптимизировать алгоритм: время выполнения немного меньше на несколько строк из-за уменьшенного буфера.

Давайте попробуем с большим файлом. Что если нам нужно прочитать файл журнала 10 МБ ?

Время выполнения на примере файла журнала объемом 10 МБ

Теперь решение № 1 намного хуже: на самом деле загрузка всего 10 МБ файла в память не очень хорошая идея. Я запускаю тесты также на 1 МБ и 100 МБ файле, и это практически та же ситуация.

А для крошечных файлов журнала? Это график для файла 10 КБ :

Время выполнения на примере файла журнала 10 КБ

Решение № 1 сейчас самое лучшее! Загрузка 10 КБ в памятьне имеет большого значения для PHP. Также № 4 и № 5 работает хорошо. Однако это крайний случай: журнал 10 КБ означает что-то вроде 150/200 строк .

Вы можете скачать все мои тестовые файлы, источники и результаты здесь .

Заключительные мысли

Решение № 5 настоятельно рекомендуется для общего случая использования: работает отличный с каждым размером файла и особенно хорошо работает при чтении нескольких строк.

Избегайте решения № 1 , если вы следует читать файлы размером более 10 КБ.

Читайте также: