Как считать 10 последних строк файла?

Сабж в заголовке. Файл весь грузить не хочу - он может быть большим. Хочу замутить что-то на тему fseek/fgets, но не знаю как именно... Надо ведь именно с конца файла, а fgets читает вперед, а не назад.
  • Вопрос задан
  • 577 просмотров
Пригласить эксперта
Ответы на вопрос 5
Immortal_pony
@Immortal_pony Куратор тега PHP
$file = new SplFileObject("file.txt", "r");
$file->seek(PHP_INT_MAX);
$lastLine = $file->key();
$lines = new LimitIterator($file, $lastLine-5, $lastLine);
var_dump(iterator_to_array($lines));
Ответ написан
Stimulate
@Stimulate
могу
$lines = file('./file.txt');
$last_10 = array_slice($lines , -10);

print_r($last_10);
Ответ написан
@necrodeflorator
Именно на пхп надо? В линухе есть tail как раз делает что тебе надо.

На пыхе наверно fseek на последний символ и читать один символ, потом fseek на предпоследний и так далее, складывая это дело в стек, проверяя не перенос ли это. Если перенос- писать в стек строк и начинать копить ещё одну строку. Но выглядит как-то муторно, да и кодировку файла нужно знать, и переносы в разных осях разные, тоже надо учитывать.
Ответ написан
Stalker_RED
@Stalker_RED
Без ООП, зато не нужно лопатить весь файл целиком.
// 4096 отступ от конца файла. Число с потолка, если знаете примерную длину строк, можете указать более подходящее число
$lines = get_lines('/pant/to/somefile.txt', 10, 4096); 
print_r($lines);

function get_lines($fileName, $linesLimit, $tailOffset = 1024, $handle = null, $size = null) {
    if (!$size) $size = filesize($fileName);
    if (!$handle) $handle = fopen($fileName, 'r');
    fseek($handle, $size - $tailOffset); // установим смещение _почти_ в конец файла, отступив от конца на $tailOffset
    $lines = [];
    while (($line = fgets($handle)) !== false) {
        $lines[] = $line;
    }

    $linesCount = count($lines);
    if ($linesCount > $linesLimit) { // нашлось более десяти строк
        $result = array_slice($lines, $linesCount - $linesLimit); // берем десять последних, бинго!
    } else {
        // если получили меньше строк, увеличим отступ
        $tailOffset *= ceil($linesLimit / $linesCount);
        $result = get_lines($fileName, $linesLimit, $tailOffset, $handle, $size);
    }

    return $result;
}
Ответ написан
s5656
@s5656
Почему никто документацию не читает?
Пример на коленке, но смысл понятен.

<?php
$fp = fopen('filename', 'r');
fseek($fp, -1, SEEK_END);
$result = '';
$lineCounter = 0;
while ($lineCounter !== 10 && ftell($fp) !== 0) {
	$byte = fread($fp, 1);
	if ($byte === "\n") {
		$lineCounter++;
	}
	fseek($fp, -2, SEEK_CUR);
	$result = $byte . $result;
}

echo $result;
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы