我们编写了以下PHP脚本来将CSV文件转换为XML文件。但它被卡住了,并没有从while循环中出来来保存XML。
CSV文件的大小约为1GB,CSV文件中的行数约为1,00,000。
由于行数很多,它无法正常工作。
我的问题是:我们如何修改以下代码,使其适用于大型文件?
<?php
$delimit = "," ;
$row_count = 0 ;
$inputFilename = "feed.csv" ;
$outputFilename = 'output.xml';
$inputFile = fopen($inputFilename, 'rt');
$headers = fgetcsv($inputFile);
$doc = new DomDocument();
$doc->formatOutput = true;
$root = $doc->createElement('rows');
$root = $doc->appendChild($root);
while (($row = fgetcsv($inputFile)) !== FALSE)
{
$container = $doc->createElement('row');
foreach ($headers as $i => $header)
{
$arr = explode($delimit, $header);
foreach ($arr as $j => $ar)
{
$child = $doc->createElement(preg_replace("/[^A-Za-z0-9]/","",$ar));
$child = $container->appendChild($child);
$whole = explode($delimit, $row[$i]);
$value = $doc->createTextNode(ltrim( rtrim($whole[$j], '"') ,'"'));
$value = $child->appendChild($value);
}
}
$root->appendChild($container);
echo "." ;
}
echo "Saving the XML now" ;
$result = $doc->saveXML();
echo "Writing to XML file now" ;
$handle = fopen($outputFilename, "w");
fwrite($handle, $result);
fclose($handle);
return $outputFilename;
&GT;
编辑:
在php.ini中,memory_limit和执行时间设置为unlimited&amp;最大值。我正在使用命令行执行。
答案 0 :(得分:1)
正如您所注意到的,您遇到了如此大的输入/输出的资源问题。
您使用的输入处理fgetcsv()
已经非常有效,因为它一次读取一行。
在这种情况下输出是问题。将整个1GB原始文本存储到DOMDocument对象中,这会为所需的内存增加相当大的开销。
但是根据你的代码,你只将xml写回一个文件,因此你不需要在运行时将它作为DOMDocument。
最简单的解决方案是将xml字符串构建为字符串并将其写入csv的每一行的输出文件中:使用&#39; a&#39;打开输出文件的句柄。 (fopen($outputfilename, "a");
,在循环之前写入xml标头,每循环运行fwrite每个csv-to-xml-ified元素,在循环之后写入xml页脚
答案 1 :(得分:1)
很可能是DomDocument的(错误)使用导致了你的记忆问题(正如@cypherabe已经回答的那样)。
但是,我建议您不要使用提议的字符串连接解决方案来查看XmlWriter http://php.net/manual/en/book.xmlwriter.php
XmlWriter扩展表示一个编写器,它提供非缓存,仅向前的方法来生成包含XML数据的流或文件。 此扩展可用于面向对象的样式或过程样式。
它已经与5.2.1版本的PHP捆绑在一起
答案 2 :(得分:0)
http://www.prestatraining.com/12-tips-to-optimise-your-php-ini-file-for-prestashop/
查看内存和大小限制部分(忽略它关于prestashop的事实)
听起来您的服务器上的PHP设置在执行时超时。如果您正在尝试处理1GB的文件,如果您的标准PHP.ini设置失败,我将不会感到惊讶。