2015-09-15 34 views
1

我有一個大約95.500行和28列的xlsx文件存在內存問題。 要處理這樣的大文件(超過10 MB xlsx)我寫下面的代碼,但是當我執行代碼並調用加載方法時,即使只讀取一行,也會收到內存耗盡錯誤! (我只分配到128Mb的PHP解釋器)用128Mb內存耗盡的phpexcel內存只讀大文件的第一行

請考慮以下因素:

  • 目前我嘗試只讀一個單列和接收有關內存耗盡的錯誤(見$ chunkFilter-> setRows (1,1);)

  • 解決關於閱讀的第一行這個問題後,我需要閱讀所有其他線路如果您認爲有其他的庫加載內容數據庫表

  • 或解決方案,請c onsider我更喜歡PHP作爲語言,因爲是用於此應用程序的主要語言,但我可以接受與其他語言的任何其他解決方案(如圍棋)

請,不要簡單地建議增加PHP的內存處理。我遺憾地知道這是可能的,但是這個代碼在最大隻有512Mb RAM的VPS共享服務器上運行,並且我需要保持儘可能最低的內存使用

有解決方案嗎?請看下面的代碼,我使用:

/** Define a Read Filter class implementing PHPExcel_Reader_IReadFilter to read file in "chunks" */ 
class chunkReadFilter implements PHPExcel_Reader_IReadFilter { 
    private $_startRow = 0; 
    private $_endRow = 0; 

    /** Set the list of rows that we want to read */ 
    public function setRows($startRow, $chunkSize) { 
     $this->_startRow = $startRow; 
     $this->_endRow  = $startRow + $chunkSize; 
    } 

public function readCell($column, $row, $worksheetName = '') { 
    // Only read the heading row, and the rows that are configured in $this->_startRow and $this->_endRow 
    if (($row == 1) || ($row >= $this->_startRow && $row < $this->_endRow)) { 
      return true; 
     } 
     return false; 
    } 
} 

function loadXLSFile($inputFile){ 
    // Initiate cache 
    $cacheMethod = PHPExcel_CachedObjectStorageFactory:: cache_to_sqlite3;  
    if (!PHPExcel_Settings::setCacheStorageMethod($cacheMethod)) { 
     echo date('H:i:s'), " Unable to set Cell Caching using ", $cacheMethod, 
            " method, reverting to memory", EOL; 
    } 
    $inputFileType = PHPExcel_IOFactory::identify($inputFile); 
    $objReader = PHPExcel_IOFactory::createReader($inputFileType); 
    $chunkFilter = new chunkReadFilter(); 
    // Tell the Read Filter, the limits on which rows we want to read this iteration 
    $chunkFilter->setRows(1,1); 
    // Tell the Reader that we want to use the Read Filter that we've Instantiated 
    $objReader->setReadFilter($chunkFilter); 
    $objReader->setReadDataOnly(true); 
    $objPHPExcel = $objReader->load($inputFile); 
} 

UPDATE

下面的錯誤返回的要求pamelus

PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 112 bytes) in /vendor/phpoffice/phpexcel/Classes/PHPExcel/Reader/Excel2007.php on line 471 
PHP Stack trace: 
PHP 1. {main}() dataimport.php:0 
PHP 2. loadFileToDb($inputFile = *uninitialized*, $tabletoupdate = *uninitialized*) dataimport.php:373 
PHP 3. PHPExcel_Reader_Excel2007->load($pFilename = *uninitialized*) dataimport.php:231 
+0

您可以請發佈您收到的錯誤消息嗎?或者至少有一個行號? – pamelus

+0

hi pamelus,謝謝你對我的問題的興趣,請在更新的問題上找到確切的erorr消息 – Marco

回答

1

鑑於你有低內存限制,我可以建議你的PHPExcel的替代方案可以一勞永逸地解決您的問題:Spout。它只需要10MB的內存,所以你應該很好!

loadXLSXFile()功能將成爲:

use Box\Spout\Reader\ReaderFactory; 
use Box\Spout\Common\Type; 

function loadXLSFile($inputFile) { 
    $reader = ReaderFactory::create(Type::XLSX); 
    $reader->open($inputFile); 

    foreach ($reader->getSheetIterator() as $sheet) { 
     foreach ($sheet->getRowIterator() as $row) { 
      // $row is the first row of the sheet. Do something with it 
      break; // you won't read any other rows 
     } 
     break; // if you only want to read the first sheet 
    } 

    $reader->close(); 
} 

就這麼簡單!無需緩存,過濾器和其他優化:)

+0

嗨Adrien,謝謝你的建議,但據我所知Spout不支持公式是這樣嗎?有時我的文件將包含一些字段的公式(只是%增量) – Marco

+0

XLSX文件應包含給定公式的計算值。所以即使這個單元格包含了類似'= A1 + B1'的東西,它也包含了結果。 Spout應該能夠讀取並返回這個結果。 – Adrien