Я пытаюсь прочитать большой файл (около 5 миллионов строк), он достигает предела памяти. Есть ли способ, которым я могу прочитать файл в определенной строке, затем увеличить счетчик и продолжить со следующей строки?
Вот код, с которым я работаю, как мне добавить указатель на начальную строку для fgets?
$handle = @fopen("large_file.txt", "r");
if($handle){
while(($buffer = fgets($handle, 4096)) !== false){
//get the content of the line
}
}
Я не пытаюсь прочитать только одну конкретную строку, я пытаюсь прочитать, скажем, от строки 1 до строки 10 000, а затем начать снова со строки 10 001 до еще 10 000 строк, вот так.
Попробуйте использовать эту функцию, вы должны использовать итерацию и получать строку за диапазоном.
$file = new SplFileObject('yourfile.txt');
echo getLineRange(1,10000);
function getLineRange($start,$end){
$tmp = "";
for ($i = $start; $i <= $end; $i++) {
$tmp .= $file->seek($i);
}
return($tmp);
}
я думаю, что ответ будет здесь Чтение определенной строки файла в php
Вы можете использовать поиск, чтобы получить конкретное местоположение линии
$file = new SplFileObject('yourfile.txt');
$file->seek(123); // seek to line 124 (0-based)
Пакетная обработка большого файла в блоках может быть выполнена в PHP, используя fseek()
/ftell()
и сохранение контекста между кусками. (SplFileObject::seek()
может искать прямо по линии, но, кажется, имеет проблемы с производительностью больших файлов.)
Предполагая, что у вас есть какой-то пакетный процессор, следующий пример должен дать вам представление о методе. Это не проверено, но получено из кода в производстве.
<?php
$context = array(
'path' => 'path/to/file',
'limit' => 1000,
'line' => NULL,
'position' => NULL,
'size' => NULL,
'percentage' => 0,
'complete' => FALSE,
'error' => FALSE,
'message' => NULL,
);
function do_chunk($context) {
$handle = fopen($context['path'], 'r');
if (!$handle) {
$context['error'] = TRUE;
$context['message'] = 'Cannot open file for reading: ' . $context['path'];
return;
}
// One-time initialization of file parameters.
if (!isset($context['size'])) {
$fstat = fstat($handle);
$context['size'] = $fstat['size'];
$context['position'] = 0;
$context['line'] = 0;
}
// Seek to position for current chunk.
$ret = fseek($handle, $context['position']);
if ($ret === -1) {
$context['error'] = TRUE;
$context['message'] = 'Cannot seek to ' . $context['position'];
fclose($handle);
return;
}
$k = 1;
do {
$context['line']++;
$raw_line = fgets($handle);
if ($raw_line) {
// Strip newline.
$line = rtrim($raw_line);
// Code to process line here.
list($error, $message) = my_process_line($context, $line);
if ($error) {
$context['error'] = TRUE;
$context['message'] = $message;
fclose($handle);
return;
}
} elseif (($raw_line === FALSE) && !feof($handle)) {
$context['error'] = TRUE;
$context['message'] = 'Unexpected error reading ' . $context['path'];
fclose($handle);
return;
}
}
while ($k++ < $context['limit'] && $raw_line);
// Save position of next chunk.
$position = ftell($handle);
if ($position !== FALSE) {
$context['position'] = $position;
} else {
$context['error'] = TRUE;
$context['message'] = 'Cannot retrieve file pointer in ' . $context['path'];
fclose($handle);
return;
}
if (!$raw_line) {
$context['complete'] = TRUE;
$context['percentage'] = 1;
} else {
$context['percentage'] = $context['position'] / $context['size'];
}
fclose($handle);
}// Batch driver for testing only - use a batch processor in production.
while ($context['complete']) {
do_batch($context);
}
if ($context['error']) {
print 'error: ' . $context['message'];
} else {
print 'complete';
}