2016-02-18 33 views
1

我們編寫了以下PHP腳本將CSV文件轉換爲XML文件。但它卡住了,並沒有從while循環中保存XML。PHP腳本將csv轉換爲XML不適用於大文件(大約1GB)

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; 

>

被修改:

在php.ini memory_limit的和執行時間被設定爲無限&最大。我正在執行使用命令行。

+0

你有PHP顯示錯誤嗎?總是在開發代碼時,'error_reporting(E_ALL); ini_set('display_errors',1);'在腳本的頂部。你很可能正在耗盡你的記憶力。如果這是一次性的,你可以暫時增加它。 –

+1

將內存限制增加到3GB並非真正的選擇。改用http://php.net/manual/en/book.xmlwriter.php。我相信如果你按照這個教程http://codeinthehole.com/writing/creating-large-xml-files-with-php/你可以自己回答這個問題。 –

+0

@Alex Blex,我認爲,您的第二個鏈接可能會解決問題。讓我現在檢查它。 – Mani

回答

1

正如您所注意到的,您遇到了如此大的輸入/輸出的資源問題。

您使用的輸入處理,fgetcsv()已經相當有效,因爲它一次只讀取一行。 輸出是這種情況下的問題。您將整個1GB原始文本存儲到DOMDocument對象中,這會增加所需內存的相當大的開銷。

但根據你的代碼,你只能將xml寫回到一個文件中,所以在運行時你並不需要它作爲DOMDocument。

最簡單的解決方案是將xml字符串構建爲字符串,並將其寫入輸出文件中csv的每一行:打開輸出文件句柄'a'(fopen($outputfilename, "a");,在循環前寫入xml頭,每循環運行fwrite每個csv-to-xml-ified元素,在循環後編寫xml頁腳

1

這很可能是導致內存問題的DomDocument的(錯誤)用法(正如@cypherabe所回答的那樣) 。但

,而不是提出字符串連接的解決方案,我會勸你看看在的XmlWriter http://php.net/manual/en/book.xmlwriter.php

的XmlWriter的擴展名代表作家提供了一個非緩存,只進意味着產生流或包含XML數據的文件。 此擴展可用於面向對象的風格或過程風格。

它已經與PHP 5.2.1版捆綁在一起

+0

看到我對OP的評論。 – michi