如何逐行读取大文件?

时间:2012-11-06 07:49:10

标签: php

我希望逐行读取文件,但不要将其完全加载到内存中。

我的文件太大而无法在内存中打开,如果尝试这样做,我总是会出现内存错误。

文件大小为1 GB。

14 个答案:

答案 0 :(得分:628)

您可以使用fgets()函数逐行读取文件:

$handle = fopen("inputfile.txt", "r");
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        // process the line read.
    }

    fclose($handle);
} else {
    // error opening the file.
} 

答案 1 :(得分:116)

if ($file = fopen("file.txt", "r")) {
    while(!feof($file)) {
        $line = fgets($file);
        # do same stuff with the $line
    }
    fclose($file);
}

答案 2 :(得分:73)

您可以为文件使用面向对象的接口类 - SplFileObject http://php.net/manual/en/splfileobject.fgets.php(PHP 5> = 5.1.0)

<?php

$file = new SplFileObject("file.txt");

// Loop until we reach the end of the file.
while (!$file->eof()) {
    // Echo one line from the file.
    echo $file->fgets();
}

// Unset the file to call __destruct(), closing the file handle.
$file = null;

答案 3 :(得分:40)

如果您要打开一个大文件,您可能希望使用生成器和fgets()来避免将整个文件加载到内存中:

this.minDate = {year: 2017, month: 1, day: 1};

像这样使用:

/**
 * @return Generator
 */
$fileData = function() {
    $file = fopen(__DIR__ . '/file.txt', 'r');

    if (!$file)
        die('file does not exist or cannot be opened');

    while (($line = fgets($file)) !== false) {
        yield $line;
    }

    fclose($file);
};

这样您就可以在foreach()中处理单个文件行。

注意:生成器需要&gt; = PHP 5.5

答案 4 :(得分:28)

使用缓冲技术读取文件。

$filename = "test.txt";
$source_file = fopen( $filename, "r" ) or die("Couldn't open $filename");
while (!feof($source_file)) {
    $buffer = fread($source_file, 4096);  // use a buffer of 4KB
    $buffer = str_replace($old,$new,$buffer);
    ///
}

答案 5 :(得分:26)

有一个file()函数返回文件中包含的行数组。

foreach(file('myfile.txt') as $line) {
   echo $line. "\n";
}

答案 6 :(得分:14)

foreach (new SplFileObject(__FILE__) as $line) {
    echo $line;
}

答案 7 :(得分:6)

小心'while(!feof ... fgets()'的东西,fgets可以得到错误(returnfing false)并永远循环而不会到达文件末尾.codaddict最接近正确但是当你的'当fgets'循环结束时,检查feof;如果不是,那么你有一个错误。

答案 8 :(得分:5)

此问题的一个流行解决方案将出现新线字符的问题。使用简单的str_replace可以很容易地修复它。

$handle = fopen("some_file.txt", "r");
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        $line = str_replace("\n", "", $line);
    }
    fclose($handle);
}

答案 9 :(得分:5)

并非所有答案中都有明显的答案。 PHP具有一个精巧的流分隔符解析器,可用于此目的。

$fp=fopen("/path/to/the/file", "r+");
while ($line = stream_get_line($fp, 1024 * 1024, "\n"))
{
echo $line;
}
fclose($fp);

答案 10 :(得分:4)

这是我如何处理非常大的文件(测试高达100G)。它比fgets()

更快
$block =1024*1024;//1MB or counld be any higher than HDD block_size*2
if ($fh = fopen("file.txt", "r")) { 
    $left='';
    while (!feof($fh)) {// read the file
       $temp = fread($fh, $block);  
       $fgetslines = explode("\n",$temp);
       $fgetslines[0]=$left.$fgetslines[0];
       if(!feof($fh) )$left = array_pop($lines);           
       foreach ($fgetslines as $k => $line) {
           //do smth with $line
        }
     }
}
fclose($fh);

答案 11 :(得分:2)

SplFileObject在处理大文件时非常有用。

success()

答案 12 :(得分:0)

<?php
echo '<meta charset="utf-8">';

$k= 1;
$f= 1;
$fp = fopen("texttranslate.txt", "r");
while(!feof($fp)) {
    $contents = '';
    for($i=1;$i<=1500;$i++){
        echo $k.' -- '. fgets($fp) .'<br>';$k++;
        $contents .= fgets($fp);
    }
    echo '<hr>';
    file_put_contents('Split/new_file_'.$f.'.txt', $contents);$f++;
}
?>

答案 13 :(得分:-7)

使用数组返回读取的函数

function read_file($filename = ''){
    $buffer = array();
    $source_file = fopen( $filename, "r" ) or die("Couldn't open $filename");
    while (!feof($source_file)) {
        $buffer[] = fread($source_file, 4096);  // use a buffer of 4KB
    }
    return $buffer;
}