我怎样才能最有效地读取php中大文本文件的前n行?

时间:2015-05-10 18:15:34

标签: php fopen fgets fread feof

到目前为止,我能够返回整个文件或空字符串。但不是预期的文件的第一行n

echo head('/path/to/my_file.txt',100); // returns '', or in other versions `1\n1\n...`

function head($filepath, $lines = 1, $adaptive = true) {

    // Open file
    $f = @fopen($filepath, "rb");
    if ($f === false) return false;

    // Sets buffer size
    if (!$adaptive) $buffer = 4096;
    else $buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096));

    // Start reading
    $output = '';
    while($line = fgets($f,$buffer) !== false) {
        if (feof($f)) break;
        $output .= $line . "\n";
    }

    // Close file and return
    fclose($f);
    return trim($output);

}

相反,以下tail函数(source)完美运行:

function tail($filepath, $lines = 1, $adaptive = true) {

    // Open file
    $f = @fopen($filepath, "rb");
    if ($f === false) return false;

    // Sets buffer size
    if (!$adaptive) $buffer = 4096;
    else $buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096));

    // Jump to last character
    fseek($f, -1, SEEK_END);

    // Read it and adjust line number if necessary
    // (Otherwise the result would be wrong if file doesn't end with a blank line)
    if (fread($f, 1) != "\n") $lines -= 1;

    // Start reading
    $output = '';
    $chunk = '';

    // While we would like more
    while (ftell($f) > 0 && $lines >= 0) {

        // Figure out how far back we should jump
        $seek = min(ftell($f), $buffer);

        // Do the jump (backwards, relative to where we are)
        fseek($f, -$seek, SEEK_CUR);

        // Read a chunk and prepend it to our output
        $output = ($chunk = fread($f, $seek)) . $output;

        // Jump back to where we started reading
        fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);

        // Decrease our line counter
        $lines -= substr_count($chunk, "\n");

    }

    // While we have too many lines
    // (Because of buffer size we might have read too many)
    while ($lines++ < 0) {

        // Find first newline and remove all text before that
        $output = substr($output, strpos($output, "\n") + 1);

    }

    // Close file and return
    fclose($f);
    return trim($output);

}

2 个答案:

答案 0 :(得分:2)

// here the correction => apply parenthesis before ...
while(($line = fgets($f)) !== false) {
    if (feof($f)) break;
    if ($lines-- == 0) break;
    $output .= $line . "\n";
}

答案 1 :(得分:1)

您只需要计算读取的行数,并在达到$行后中止。

 $i = 0;
 while($line = fgets($file) !== false) {
        if (feof($file)) break;
        $output .= $line . "\n";
        if ($i++ >= $lines) {
          break;
        }
    }