用于在PHP中读取文件的最少内存密集型方法

时间:2010-07-03 10:17:56

标签: php file

我正在使用Php中的file()函数读取包含大约50k行的文件。但是,由于文件内容作为数组存储在内存中,因此会发出内存不足错误。还有其他办法吗?

此外,存储的行的长度是可变的。

这是代码。该文件也是700kB而不是mB。

private static function readScoreFile($scoreFile)
{
    $file = file($scoreFile);
    $relations = array();

    for($i = 1; $i < count($file); $i++)
    {
        $relation = explode("\t",trim($file[$i]));
        $relation = array(
                        'pwId_1' => $relation[0],
                        'pwId_2' => $relation[1],
                        'score' => $relation[2],
                        );
        if($relation['score'] > 0)
        {
            $relations[] = $relation;
        }
    }

    unset($file);
    return $relations;
}

5 个答案:

答案 0 :(得分:13)

使用fopenfreadfclose按顺序读取文件:

$handle = fopen($filename, 'r');
if ($handle) {
    while (!feof($handle)) {
        echo fread($handle, 8192);
    }
    fclose($handle);
}

答案 1 :(得分:9)

更新问题和comments to answer of fabjoa

编辑

如果700kb文件使用您提供的代码消耗140MB内存,那肯定有些可疑(尽管在每次迭代结束时你可以unset $关系)。考虑使用调试器逐步执行它以查看会发生什么。您可能还需要考虑重写代码以使用SplFileObject's CSV functionsor their procedural cousins

SplFileObject::setCsvControl example

$file = new SplFileObject("data.csv");
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl('|');
foreach ($file as $row) {
    list ($fruit, $quantity) = $row;
    // Do something with values
}

对于迭代文件的OOP方法,请尝试SplFileObject

SplFileObject::fgets example

$file = new SplFileObject("file.txt");
while (!$file->eof()) {
    echo $file->fgets();
}

SplFileObject::next example

// Read through file line by line
$file = new SplFileObject("misc.txt");
while (!$file->eof()) {
    echo $file->current();
    $file->next();
}

甚至

foreach(new SplFileObject("misc.txt") as $line) {
    echo $line;
}

非常相关(如果不是重复):

答案 2 :(得分:1)

如果您不知道最大行长度并且您不习惯使用幻数来表示最大行长度,那么您需要对文件进行初始扫描并确定最大行长度。

除此之外,以下代码可以帮助您:

    // length is a large number or calculated from an initial file scan
    while (!feof($handle)) {
        $buffer = fgets($handle, $length);
        echo $buffer;
    }

答案 3 :(得分:0)

在操作期间分配更多内存,可能类似于ini_set('memory_limit','16M');.操作完成后,不要忘记返回初始内存分配

答案 4 :(得分:0)

一个老问题,但是由于我没有看到任何人提及它,PHP generators是减少保存内存消耗的好方法。

例如:

function read($fileName)
{
    $fileHandler = fopen($fileName, 'rb');

    while(($line = fgets($fileHandler)) !== false) {
        yield rtrim($line, "\r\n");
    }

    fclose($fileHandler);
}

foreach(read(__DIR__ . '/filenameHere') as $line) {
    echo $line;
}