尝试在[NSBundle bundleWithIdentifier:@"org.cocoapods.xyz"]
循环中使用array_combine
时遇到了麻烦。它最终会出错:
foreach
这是我的代码:
PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 85 bytes) in
我使用的源文件CSV大约有1,000,000行。这一行
$data = array();
$csvData = $this->getData($file);
if ($columnNames) {
$columns = array_shift($csvData);
foreach ($csvData as $keyIndex => $rowData) {
$data[$keyIndex] = array_combine($columns, array_values($rowData));
}
}
return $data;
我使用while循环读取CSV并将其分配到一个数组中,它没有任何问题。麻烦来自$csvData = $this->getData($file)
和array_combine
循环。
您有什么想法解决这个问题,或者只是想找到更好的解决方案吗?
以下是读取CSV文件的代码(使用while循环)
foreach
如果你正在使用CSV文件< = 20,000~30,000行,上面的代码没有任何问题。从50,000行以上,内存将耗尽。
答案 0 :(得分:4)
事实上,您在整个数据集中保留(或试图保留)两个不同的副本。首先,使用getData()
将整个CSV日期加载到内存中,然后通过循环内存中的数据并创建新数组,将数据复制到$data
数组中。
在加载CSV数据时,您应该使用基于流的读取,以便只在内存中保留一个数据集。如果您使用的是PHP 5.5+(顺便说一句,您应该这样做),这很简单,只需将getData
方法更改为:
protected function getData($file) {
if (!file_exists($file)) {
throw new Exception('File "' . $file . '" do not exists');
}
$fh = fopen($file, 'r');
while ($rowData = fgetcsv($fh, $this->_lineLength, $this->_delimiter, $this->_enclosure)) {
yield $rowData;
}
fclose($fh);
}
这使用了一个所谓的generator,这是一个PHP> = 5.5的功能。其余的代码应该继续工作,因为getData
的内部工作方式应该对调用代码透明(只有事实的一半)。
更新以解释如何解压缩列标题现在可以正常工作。
$data = array();
$csvData = $this->getData($file);
if ($columnNames) { // don't know what this one does exactly
$columns = null;
foreach ($csvData as $keyIndex => $rowData) {
if ($keyIndex === 0) {
$columns = $rowData;
} else {
$data[$keyIndex/* -1 if you need 0-index */] = array_combine(
$columns,
array_values($rowData)
);
}
}
}
return $data;