2013-02-13 35 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您可以稍后设置位置....