У меня есть файл размером 200 КБ, что я использую на нескольких страницах, но на каждой странице мне нужно всего 1-2 строки этого файла, так как я могу читать только эти строки, что мне нужно, если я знаю номер строки?
Например, если мне нужна только 10-я строка, я не хочу загружать в память все строки, только 10-ю строку.
Извините за мой плохой английский!
Если вы не знаете смещение линии, вам нужно будет прочитать каждую строку до этой точки. Вы можете просто выбросить старые строки (которые вам не нужны), перейдя через файл с чем-то вроде fgets()
. (EDIT: Вместо fgets()
я бы предложил решение @Gordon )
Возможно, лучшим решением будет использование базы данных, поскольку механизм базы данных будет выполнять работу по хранению строк и позволит вам (очень эффективно) получить определенную «строку» (это не будет строка, а запись с числовой идентификатор, однако он составляет одно и то же), без необходимости читать записи перед ним.
Попробуйте SplFileObject
echo memory_get_usage(), PHP_EOL; // 333200 $file = new SplFileObject('bible.txt'); // 996kb $file->seek(5000); // jump to line 5000 (zero-based) echo $file->current(), PHP_EOL; // output current line echo memory_get_usage(), PHP_EOL; // 342984 vs 3319864 when using file()
Для вывода текущей строки вы можете либо использовать current()
либо просто echo $file
. Однако я нахожу более понятным использовать этот метод. Вы также можете использовать fgets()
, но это приведет к следующей строке.
Конечно, вам нужны только три средних линии. Я добавил вызовы memory_get_usage
только для того, чтобы доказать, что этот подход почти не содержит памяти.
Изменилось ли содержимое файла? Если он является статичным или относительно статическим, вы можете создать список смещений, где вы хотите прочитать свои данные. Например, если файл меняется один раз в год, но вы читаете его сотни раз в день, тогда вы можете предварительно вычислить смещения строк, которые вы хотите, и перейти к ним прямо следующим образом:
$offsets = array(); while ($line = fread($filehandle)) { .... find line 10 .... } $offsets[10] = ftell($filehandle); // store line 10's location .... find next line $offsets[20] = ftell($filehandle);
и так далее. Впоследствии вы можете тривиально перейти к местоположению этой строки следующим образом:
$fh = fopen('file.txt', 'rb'); fseek($fh, $offsets[20]); // jump to line 20
Но это вполне может быть излишним. Попробуйте провести сравнительный анализ операций – сравните, сколько времени требуется, чтобы выполнить старомодные «читать 20 строк» против прекомпуте / прыжка.
<?php $lines = array(1, 2, 10); $handle = @fopen("/tmp/inputfile.txt", "r"); if ($handle) { $i = 0; while (!feof($handle)) { $line = stream_get_line($handle, 1000000, "\n"); if (in_array($i, $lines)) { echo $line; $line = ''; // Don't forget to clean the buffer! } if ($i > end($lines)) { break; } $i++; } fclose($handle); } ?>
Просто пропустите их без сохранения, например
$i = 1; $file = fopen('file.txt', 'r'); while (!feof($file)) { $line = fgets($file); // this gets whole line from the file; if ($i == 10) { break; // break on tenth line } $i ++; }
Вышеприведенный пример сохранит память только для последней строки, полученной из файла, так что это самый эффективный для памяти способ сделать это.
используйте fgets () . 10 раз :-), в этом случае вы не будете хранить все 10 строк в памяти
Почему вы только пытаетесь загрузить первые десять строк? Знаете ли вы, что загрузка всех этих строк на самом деле является проблемой?
Если вы не измерили, то вы не знаете, что это проблема. Не тратьте время на оптимизацию времени на отсутствие проблем. Скорее всего, любое изменение производительности, которое вы будете иметь при загрузке всего файла 200K, будет незаметным, если вы не знаете, что загрузка этого файла действительно является узким местом.