【发布时间】:2012-11-02 15:03:00
【问题描述】:
[已编辑的 OP 在这里是简短版本]
遍历文件并读取内容,然后写入会导致函数失败。这似乎是一个内存问题。这是我试过的三个版本。
第一次尝试这个:
$file = new SplFileObject($this->getDirectoryPath() . $this->getFileName(), "a+");
$file->setFlags(SplFileObject::DROP_NEW_LINE | SplFileObject::SKIP_EMPTY);
if ($this->exists()) {
foreach ($file as $line) {
$tempArray = unserialize($line);
if ($tempArray['Key'] == $arrayOfData['Key']) {
foreach ($totalsToBeAdded as $key) {
$arrayOfData[$key] += $tempArray[$key];
}
}
}
}
$tempString = serialize($arrayOfData);
$file->fwrite("$tempString\r\n");
$this->numLines++;
然后我尝试了这个:
$file = new SplFileObject($this->getDirectoryPath() . $this->getFileName(), "a+");
$file->setFlags(SplFileObject::DROP_NEW_LINE | SplFileObject::SKIP_EMPTY);
if ($this->exists()) {
while (!$file->eof()) {
$tempArray = unserialize($file->current());
if ($tempArray['PartNumber'] == $arrayOfData['PartNumber']) {
foreach ($totalsToBeAdded as $key) {
$arrayOfData[$key] += $tempArray[$key];
}
}
$file->next();
}
}
$tempString = serialize($arrayOfData);
$file->fwrite("$tempString\r\n");
$this->numLines++;
最后我放弃了 SplFileObject 并使用普通的 fopen 等:
$handle = fopen($this->getDirectoryPath() . $this->getFileName(), "a+");
if ($this->exists()) {
while (false !== ($line = fgets($handle))) {
$tempArray = unserialize(trim($line));
if ($tempArray['Key'] == $arrayOfData['Key']) {
foreach ($totalsToBeAdded as $key) {
$arrayOfData[$key] += $tempArray[$key];
}
}
}
}
$tempString = serialize($arrayOfData);
fwrite($handle, "$tempString\r\n");
fclose($handle);
$this->numLines++;
编辑以获取更多信息:
我很好奇 PHP 的底层代码在逐行遍历文件时是否使用数组作为迭代器,这可能会杀死它。
而且文件确实开始构建,我可以看到它写入到大约 500-600k 然后它就死了。
最终文件大小约为 10mb。
最后一次更新:
这可行(注意缺少打开和读取文件):
public function writeUnique($arrayOfData, $totalsToBeAdded) {
$tempArray = array();
$handle = fopen($this->fullPath, "a+");
$tempString = serialize($arrayOfData);
fwrite($handle, "$tempString\r\n");
fclose($handle);
$this->numLines++;
}
虽然这会中断(注意所有正在执行的操作都是循环整个文件然后写入文件):
public function writeUnique($arrayOfData, $totalsToBeAdded) {
$tempArray = array();
$handle = fopen($this->fullPath, "a+");
if ($this->exists()) {
while (false !== ($line = fgets($handle))) {
}
}
$tempString = serialize($arrayOfData);
fwrite($handle, "$tempString\r\n");
fclose($handle);
$this->numLines++;
}
更新三号:
我现在已经测试过了:
public function writeUnique($arrayOfData, $totalsToBeAdded) {
$handle = fopen($this->fullPath, "a+");
if ($this->exists()) {
while (false !== ($line = fgets($handle))) {
}
}
$tempString = serialize($arrayOfData);
// fwrite($handle, "$tempString\r\n"); Commented out the writing.
fclose($handle);
$this->numLines++;
}
这行得通。没有失败,内存错误或其他方面。
因此,这似乎要么是重复读取大文件的相同行的问题,要么是函数的写入部分在某种程度上踩到了读取函数的脚趾。老实说,这并没有没道理。我知道每个人都认为这与我的阵列有关。但是我已经完全排除了我所有的逻辑,我只是想读/写一个大文件。
【问题讨论】:
-
trime($line)是一个错字,你的意思是trim还是你自定义的函数?显然PHP没有trime()函数 -
您的示例都没有显示 $arrayOfData 或 $totalsToBeAdded 变量的来源。我怀疑当您解析文件时,您会不断添加这些变量并最终耗尽空间?
-
@D-Rock:没有 $arrayOfData 是来自数据库查询的数组。它是 10 列的键 => 值设置。
-
@Anthony:你是对的,这只是一个错字。在源代码中是正确的。