我想逐行读取文件,但不完全加载到内存中。

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

文件大小为1gb。


当前回答

这就是我如何处理非常大的文件(测试高达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);

其他回答

对于这个问题,一个流行的解决方案是使用新的行字符。使用简单的str_replace就可以很容易地修复这个问题。

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

如果你想在打开一个大文件时使用foreach而不是while,你可能想在Generator中封装while循环,以避免将整个文件加载到内存中:

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

    if (!$file) {
        return; // die() is a bad practice, better to use return
    }    
    while (($line = fgets($file)) !== false) {
        yield $line;
    }

    fclose($file);
};

像这样使用它:

foreach ($fileData() as $line) {
    // $line contains current line
}

通过这种方式,您可以在foreach()中处理单个文件行。

注意:生成器需要>= PHP 5.5

foreach (new SplFileObject(__FILE__) as $line) {
    echo $line;
}
<?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++;
}
?>

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

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