2013-02-13 53 views
7

我想解析一個大小約爲1GB的製表符分隔文件。讀取和分析非常大的文件的內容

當我運行該腳本,我得到:

Fatal error: Allowed memory size of 1895825408 bytes exhausted (tried to allocate 1029206974 bytes) ... 

我此刻的腳本就是:

$file = file_get_contents('allCountries.txt') ; 

$file = str_replace(array("\r\n", "\t"), array("[NEW*LINE]", "[tAbul*Ator]"), $file) ; 

我已經設置php.ini中的內存限制爲-1,然後給我:

Fatal error: Out of memory (allocated 1029963776) (tried to allocate 1029206974 bytes) 

反正是有部分打開該文件,然後使更少的內存用完移動到下一部分一次?

+1

爲什麼不逐行處理文件? – 2013-02-13 08:04:26

回答

10

是的,你可以逐行閱讀:

$handle = @fopen("/tmp/inputfile.txt", "r"); 
if ($handle) { 
    while (($buffer = fgets($handle, 4096)) !== false) { 
     echo $buffer; 
    } 
    fclose($handle); 
} 
+1

對於製表符分隔的文件,爲簡單起見,請使用fgetcsv() – 2013-02-13 08:49:00

1

你確定它的fopen多數民衆贊成失敗,而不是你的腳本的超時設置?默認值通常在30秒左右,如果你的文件花費的時間比讀入的時間要長,那麼它可能會跳過它。

另一件需要考慮的事情可能是腳本的內存限制 - 將文件讀入數組可能會導致此問題,因此請檢查錯誤日誌中的內存警告。

如果以上都不是您的問題,您可以考慮使用fgets逐行讀取文件,按照處理方式進行處理。

$handle = fopen("/tmp/uploadfile.txt", "r") or die("Couldn't get handle"); 
if ($handle) { 
    while (!feof($handle)) { 
     $buffer = fgets($handle, 4096); 
     // Process buffer here.. 
    } 
    fclose($handle); 
} 

編輯

PHP似乎沒有引發錯誤,它只是返回false。

相對於腳本運行的地方,$rawfile的路徑是否正確?也許嘗試在這裏設置文件名的絕對路徑。

+0

如果我只是將文件加載到內存中,它發生在大約2秒鐘內,錯誤發生在str_replace上,但我會嘗試逐行建議。 – imperium2335 2013-02-13 08:07:26

+0

錯誤與str_replace發生,因爲在這種情況下,PHP嘗試將相同大小的內存複製到另一個變量 – 2013-02-13 08:11:38

1

是,使用的fopen和FREAD /與fgets此:

http://www.php.net/manual/en/function.fread.php

string fread (resource $handle , int $length) 

設置$長度有多少要讀取的文件。 $ handle爲新讀取保存位置,然後使用fseek您可以稍後設置位置....