我正在使用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;
}
答案 0 :(得分:13)
$handle = fopen($filename, 'r');
if ($handle) {
while (!feof($handle)) {
echo fread($handle, 8192);
}
fclose($handle);
}
答案 1 :(得分:9)
编辑:
如果700kb文件使用您提供的代码消耗140MB内存,那肯定有些可疑(尽管在每次迭代结束时你可以unset
$关系)。考虑使用调试器逐步执行它以查看会发生什么。您可能还需要考虑重写代码以使用SplFileObject's CSV functions(or 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
:
$file = new SplFileObject("file.txt");
while (!$file->eof()) {
echo $file->fgets();
}
// 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;
}