读取文件到特定的php行


Read File to specific line php

我正在尝试读取一个大文件(大约500万行),它一直达到内存限制。有没有一种方法可以把文件读到特定的一行,然后增加一个计数器,从下一行继续?

以下是我正在处理的代码,如何添加指向fgets起始行的指针?

$handle = @fopen("large_file.txt", "r");
if($handle){
   while(($buffer = fgets($handle, 4096)) !== false){
      //get the content of the line
    }
}

我不是只读一行,我是从第1行读到第10000行,然后从第10001行再读到另外10000行,就像这样。

尝试使用此函数时,应使用迭代并逐行获取。

$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中文件的特定行

您可以使用seek获取特定线路位置的

$file = new SplFileObject('yourfile.txt');
$file->seek(123); // seek to line 124 (0-based)

可以使用fseek()/ftell()在PHP中批量处理大块文件,并在块之间保存上下文。(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';
}