Как читать только 5 последних строк текстового файла в PHP?
У меня есть файл с именем «file.txt», который обновляется, добавляя к нему строки.
Я читаю его по этому коду:
$fp = fopen("file.txt", "r"); $data = ""; while(!feof($fp)) < $data .= fgets($fp, 4096); >echo $data;
и появляется огромное количество строк. Я просто хочу повторить последние 5 строк файла
11111111111111 22222222222 33333333333333 44444444444 55555555555555 66666666666
Solutions Collecting From Web of «Как читать только 5 последних строк текстового файла в PHP?»
Непроверенный код, но должен работать:
$file = file("filename.txt"); for ($i = max(0, count($file)-6); $i
Вызов max будет обрабатывать файл менее 6 строк.
Для большого файла чтение всех строк в массив с файлом () немного расточительно. Вот как вы можете прочитать файл и сохранить буфер из последних 5 строк:
$lines=array(); $fp = fopen("file.txt", "r"); while(!feof($fp)) < $line = fgets($fp, 4096); array_push($lines, $line); if (count($lines)>5) array_shift($lines); > fclose($fp);
в$lines=array(); $fp = fopen("file.txt", "r"); while(!feof($fp)) < $line = fgets($fp, 4096); array_push($lines, $line); if (count($lines)>5) array_shift($lines); > fclose($fp);
Вы могли бы оптимизировать это немного больше с некоторой эвристикой относительно вероятной длины линии, стремясь к позиции, скажем, приблизительно 10 строк от конца, и идите назад, если это не дает 5 строк. Вот простая реализация, которая демонстрирует, что:
//how many lines? $linecount=5; //what's a typical line length? $length=40; //which file? $file="test.txt"; //we double the offset factor on each iteration //if our first guess at the file offset doesn't //yield $linecount lines $offset_factor=1; $bytes=filesize($file); $fp = fopen($file, "r") or die("Can't open $file"); $complete=false; while (!$complete) < //seek to a position close to end of file $offset = $linecount * $length * $offset_factor; fseek($fp, -$offset, SEEK_END); //we might seek mid-line, so read partial line //if our offset means we're reading the whole file, //we don't skip. if ($offset<$bytes) fgets($fp); //read all following lines, store last x $lines=array(); while(!feof($fp)) < $line = fgets($fp); array_push($lines, $line); if (count($lines)>$linecount) < array_shift($lines); $complete=true; >> //if we read the whole file, we're done, even if we //don't have enough lines if ($offset>=$bytes) $complete=true; else $offset_factor*=2; //otherwise let's seek even further back > fclose($fp); var_dump($lines);
в//how many lines? $linecount=5; //what's a typical line length? $length=40; //which file? $file="test.txt"; //we double the offset factor on each iteration //if our first guess at the file offset doesn't //yield $linecount lines $offset_factor=1; $bytes=filesize($file); $fp = fopen($file, "r") or die("Can't open $file"); $complete=false; while (!$complete) < //seek to a position close to end of file $offset = $linecount * $length * $offset_factor; fseek($fp, -$offset, SEEK_END); //we might seek mid-line, so read partial line //if our offset means we're reading the whole file, //we don't skip. if ($offset<$bytes) fgets($fp); //read all following lines, store last x $lines=array(); while(!feof($fp)) < $line = fgets($fp); array_push($lines, $line); if (count($lines)>$linecount) < array_shift($lines); $complete=true; >> //if we read the whole file, we're done, even if we //don't have enough lines if ($offset>=$bytes) $complete=true; else $offset_factor*=2; //otherwise let's seek even further back > fclose($fp); var_dump($lines);
function ReadFromEndByLine($filename,$lines) < /* freely customisable number of lines read per time*/ $bufferlength = 5000; $handle = @fopen($filename, "r"); if (!$handle) < echo "Error: can't find or open $filename
\n"; return -1; > /*get the file size with a trick*/ fseek($handle, 0, SEEK_END); $filesize = ftell($handle); /*don't want to get past the start-of-file*/ $position= - min($bufferlength,$filesize); while ($lines > 0) < if ($err=fseek($handle,$position,SEEK_END)) < /* should not happen but it's better if we check it*/ echo "Error $err: something went wrong
\n"; fclose($handle); return $lines; > /* big read*/ $buffer = fread($handle,$bufferlength); /* small split*/ $tmp = explode("\n",$buffer); /*previous read could have stored a partial line in $aliq*/ if ($aliq != "") < /*concatenate current last line with the piece left from the previous read*/ $tmp[count($tmp)-1].=$aliq; >/*drop first line because it may not be complete*/ $aliq = array_shift($tmp); $read = count($tmp); if ( $read >= $lines ) < /*have read too much!*/ $tmp2 = array_slice($tmp,$read-$n); /* merge it with the array which will be returned by the function*/ $lines = array_merge($tmp2,$lines); /* break the cycle*/ $lines = 0; >elseif (-$position >= $filesize) < /* haven't read enough but arrived at the start of file*/ //get back $aliq which contains the very first line of the file $lines = array_merge($aliq,$tmp,$lines); //force it to stop reading $lines = 0; >else < /*continue reading. */ //add the freshly grabbed lines on top of the others $lines = array_merge($tmp,$lines); $lines -= $read; //next time we want to read another block $position -= $bufferlength; //don't want to get past the start of file $position = max($position, -$filesize); >> fclose($handle); return $lines; >
Это будет быстро для больших файлов, но для этого достаточно простого кода, если есть БОЛЬШИЕ ФАЙЛЫ, используйте это
ReadFromEndByLine ( ‘myfile.txt’, 6);
Это общий вопрос для интервью. Вот что я написал в прошлом году, когда меня задали этот вопрос. Помните, что код, который вы получаете на Stack Overflow, имеет лицензию на использование Creative Commons Share-Alike с необходимой атрибуцией .
$c = count($lines); $i = $c >= $numLines? $c-$numLines: 0; for (; $i >
Это решение делает предположение о максимальной длине линии. Интервьюер спросил меня, как я разрешу проблему, если я не смогу сделать это предположение, и должен был разместить линии, которые были потенциально длиннее любой максимальной длины, которую я выбрал.
Я сказал ему, что любой проект программного обеспечения должен делать определенные предположения, но я мог бы проверить, было ли $c меньше желаемого количества строк, а если нет, fseek() назад дополнительно инкрементно (удваивая каждый раз), пока мы не сделаем получить достаточно строк.
Если вы используете систему Linux, вы можете сделать это:
$lines = `tail -5 /path/to/file.txt`;
В противном случае вам придется подсчитывать строки и принимать последние 5, что-то вроде:
$all_lines = file('file.txt'); $last_5 = array_slice($all_lines , -5);
Это не использует file() поэтому он будет более эффективным для огромных файлов;
= 0 ) < $c = fgetc($fp); if($c == "\n" || $c == "\r")< $lines--; if( $revers )< $read[$i] = strrev($read[$i]); $i++; >> if( $revers ) $read[$i] .= $c; else $read .= $c; $offset--; > fclose ($fp); if( $revers ) < if($read[$i] == "\n" || $read[$i] == "\r") array_pop($read); else $read[$i] = strrev($read[$i]); return implode('',$read); >return strrev(rtrim($read,"\n\r")); > //if $revers=false function return-> //line 1000: i am line of 1000 //line 1001: and i am line of 1001 //line 1002: and i am last line //but if $revers=true function return-> //line 1002: and i am last line //line 1001: and i am line of 1001 //line 1000: i am line of 1000 ?>
Большинство опций здесь предполагают читать файл в памяти, а затем работать со строками. Это не будет хорошей идеей, если файл слишком большой
Я думаю, что лучший способ – использовать некоторую ОС-утилиту, такую как «tail» в unix.
exec('tail -3 /logs/reports/2017/02-15/173606-arachni-2415.log', $output); echo $output; // 2017-02-15 18:03:25 [*] Path Traversal: Analyzing response . // 2017-02-15 18:03:27 [*] Path Traversal: Analyzing response . // 2017-02-15 18:03:27 [*] Path Traversal: Analyzing response .
Функция file () PHP считывает весь файл в массив. Это решение требует наименьшего количества ввода:
$data = array_slice(file('file.txt'), -5); foreach ($data as $line)
Открытие больших файлов с помощью file() может генерировать большой массив, сохраняя значительный объем памяти.
Вы можете уменьшить стоимость памяти с помощью SplFileObject поскольку она выполняет SplFileObject через каждую строку.
Используйте метод seek ( seekableiterator ) для получения последней строки. Затем вы должны вычесть текущее значение ключа на 5.
Чтобы получить последнюю строку, используйте PHP_INT_MAX . (Да, это обходной путь.)
$file = new SplFileObject('large_file.txt', 'r'); $file->seek(PHP_INT_MAX); $last_line = $file->key(); $lines = new LimitIterator($file, $last_line - 5, $last_line); print_r(iterator_to_array($lines));
Эта функция будет работать для ДЕЙСТВИТЕЛЬНО больших файлов под 4 ГБ. Скорость исходит от чтения большого фрагмента данных вместо 1 байта за раз и подсчета строк.
// Will seek backwards $n lines from the current position function seekLineBackFast($fh, $n = 1) < $pos = ftell($fh); if ($pos == 0) return false; $posAtStart = $pos; $readSize = 2048*2; $pos = ftell($fh); if(!$pos)< fseek($fh, 0, SEEK_SET); return false; >// we want to seek 1 line before the line we want. // so that we can start at the very beginning of the line while ($n >= 0) < if($pos == 0) break; $pos -= $readSize; if($pos // fseek returns 0 on success and -1 on error if(fseek($fh, $pos, SEEK_SET)==-1) < fseek($fh, 0, SEEK_SET); break; >$data = fread($fh, $readSize); $count = substr_count($data, "\n"); $n -= $count; if($n < 0) break; >fseek($fh, $pos, SEEK_SET); // we may have seeked too far back // so we read one line at a time forward while($n < 0)< fgets($fh); $n++; >// just in case? $pos = ftell($fh); if(!$pos) fseek($fh, 0, SEEK_SET); // check that we have indeed gone back if ($pos >= $posAtStart) return false; return $pos; >
После выполнения функции вы можете просто сделать fgets () в цикле, чтобы читать каждую строку за раз от $ fh.
Вы можете использовать мою небольшую вспомогательную библиотеку (2 функции)
//read last 5 lines $lines = \jasir\FileHelpers\FileHelpers::readLastLines($pathToFile, 5);
Я проверил это. Меня устраивает.
function getlast($filename,$linenum_to_read,$linelength) < // this function takes 3 arguments; if (!$linelength)< $linelength = 600;>$f = fopen($filename, 'r'); $linenum = filesize($filename)/$linelength; for ($i=1; $i <=($linenum-$linenum_to_read);$i++) < $data = fread($f,$linelength); >echo "
"; for ($j=1; $j <=$linenum_to_read+1;$j++) < echo fread($f,$linelength); >echo "
The filesize is:".filesize("$filename"); > getlast("file.txt",6,230); ?>
Наименьшее количество бара и выходы хорошо. Я согласен с Полом Диксоном …
$lines=array(); $fp = fopen("userlog.txt", "r"); while(!feof($fp)) < $line = fgets($fp, 4096); array_push($lines, $line); if (count($lines)>25) array_shift($lines); > fclose($fp); while ($a ".$lines[$a]; >
в$lines=array(); $fp = fopen("userlog.txt", "r"); while(!feof($fp)) < $line = fgets($fp, 4096); array_push($lines, $line); if (count($lines)>25) array_shift($lines); > fclose($fp); while ($a ".$lines[$a]; >
$dosya = "../dosya.txt"; $array = explode("\n", file_get_contents($dosya)); $reversed = array_reverse($array); for($x = 0; $xЕсли ваши линии разделены CR или LF, вы попытаетесь взломать переменную $ data:
$ lines должно быть массивом, и вы можете определить количество записей с помощью sizeof () и просто получить последние 5.
это прочитано последние 10 строк из текстового файла
$data = array_slice(file('logs.txt'),10); foreach ($data as $line) < echo $line."
"; >
- Объяснение повторно используемых структур в OO PHP
- Изменить имя модуля в Zend Framework
- PHP: Возможно ли создать объект SplFileObject из содержимого файла (строки)?
- как загрузить текстовый файл с помощью dfferent php script process
- Вложенные модели отношений в формах – Laravel
- Работа Jenkins PHP
- Проверьте, содержит ли массив другой массив с PHP
- как отключить сеанс при закрытии веб-страницы в php
- Как передать данные GET и POST в исполняемый файл php?
- Начало работы с SAML и PHP
- Ошибка PHP Parse: синтаксическая ошибка, неожиданный T_PUBLIC
- Как преобразовать элементы в массив в строку, разделенную запятой, в PHP?
- Laravel Красноречивое отношение к многим, динамически добавляя запрос к связанной таблице
- Gearman с несколькими серверами и рабочими php
- PHP SoapClient __getFunctions () возвращает типы UNKNOWN
Как получить последнюю строку из файла
Получить последнюю строку из файла
Есть файл с произвольным количеством строк, нужно получить последнюю строку этого файла, и записать.
Как получить последнюю строку из textbox?
Нужно как то вытащить самую последнюю строку из textbox. Как это сделать?
Как получить последнюю строку консоли?
Как получить последнюю строку консоли?
Как получить последнюю строку в таблице?
Есть таблица: 09.12.1212 14.12.1212 03.12.1212 Как просто получить последнюю строку в этой.
Как получить последнюю строку (не используя подзапрос)?
Столкнулся с такой задачей, необходимо из таблицы вытаскивать последнюю строку, или последнюю.
Сообщение было отмечено alanat как решение
Решение
$filename = 'log.cgi.txt'; $lines = file($filename, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); $line = array_pop($lines); echo $line; // Jun 28 09:53:56 (none) local0.err cg[30558]: b_scanreg: reg_value = 0x1b1bbd04
Ну а если файл log.cgi.txt большой, то нужно будет прочитать его построчно циклом, и взять последнюю строку:
1 2 3 4 5 6 7 8 9 10 11 12 13
$filename = 'log.cgi.txt'; $line = ''; $f = fopen($filename, 'r'); while (! feof($f)) { $line = fgets($f); } fclose($f); echo $line; // Jun 28 09:53:56 (none) local0.err cg[30558]: b_scanreg: reg_value = 0x1b1bbd04
Как прочитать только 5 последних строк текстового файла в PHP?
У меня есть файл с именем «file.txt» он обновляется, добавляя к нему строки. Я читаю его по этому коду:
$fp = fopen("file.txt", "r"); $data = ""; while(!feof($fp)) < $data .= fgets($fp, 4096); >echo $data;
и появляется огромное количество строк. Я просто хочу повторить последние 5 строк файла Как я могу это сделать? file.txt выглядит следующим образом:
11111111111111 22222222222 33333333333333 44444444444 55555555555555 66666666666
18 ответов
Неподтвержденный код, но он должен работать:
$file = file("filename.txt"); for ($i = max(0, count($file)-6); $i
Вызов max будет обрабатывать файл менее 6 строк.
это хорошо, но нужно отметить критические вопросы. то есть $ i может быть меньше 0; так что вам нужно, если ($ i> 0) echo .
Не очень хорошо, так как это потребляет много оперативной памяти даром в случае большого файла журнала.
Для большого файла чтение всех строк в массив с файлом() немного расточительно. Здесь вы можете прочитать файл и сохранить буфер из последних 5 строк:
$lines=array(); $fp = fopen("file.txt", "r"); while(!feof($fp)) < $line = fgets($fp, 4096); array_push($lines, $line); if (count($lines)>5) array_shift($lines); > fclose($fp);
Вы можете оптимизировать это немного больше с некоторой эвристикой относительно вероятной длины линии, стремясь к позиции, скажем, приблизительно 10 строк от конца, и идите назад, если это не дает 5 строк. Вот простая реализация, которая демонстрирует, что:
//how many lines? $linecount=5; //what a typical line length? $length=40; //which file? $file="test.txt"; //we double the offset factor on each iteration //if our first guess at the file offset doesn't //yield $linecount lines $offset_factor=1; $bytes=filesize($file); $fp = fopen($file, "r") or die("Can't open $file"); $complete=false; while (!$complete) < //seek to a position close to end of file $offset = $linecount * $length * $offset_factor; fseek($fp, -$offset, SEEK_END); //we might seek mid-line, so read partial line //if our offset means we're reading the whole file, //we don't skip. if ($offset<$bytes) fgets($fp); //read all following lines, store last x $lines=array(); while(!feof($fp)) < $line = fgets($fp); array_push($lines, $line); if (count($lines)>$linecount) < array_shift($lines); $complete=true; >> //if we read the whole file, we're done, even if we //don't have enough lines if ($offset>=$bytes) $complete=true; else $offset_factor*=2; //otherwise let seek even further back > fclose($fp); var_dump($lines);
@Paual Dixon, в цикле while вы читаете всю строку и сохраняете последнюю X-строку. Можно ли прочитать последние X строк?