•fgets()
直到文本文件超过 20 MBytes 并且解析速度大大降低之前,该功能都很好。
• 该file_ get_contents()
函数在 40 MBytes 之前给出了良好的结果,在 100 MBytes 之前给出了可接受的结果,但是file_get_contents()
将整个文件加载到内存中,因此它不可扩展。
• 该file()
函数对于大文本文件是灾难性的,因为该函数创建一个包含每一行文本的数组,因此该数组存储在内存中,并且使用的内存更大。
实际上,我只能设法解析一个 200 MB 的文件,memory_limit
设置为 2 GB,这对于我打算解析的 1+ GB 文件是不合适的。
当你必须解析大于 1 GB 的文件并且解析时间超过 15 秒并且你想避免将整个文件加载到内存中时,你必须找到另一种方法。
我的解决方案是以任意小块解析数据。代码是:
$filesize = get_file_size($file);
$fp = @fopen($file, "r");
$chunk_size = (1<<24); // 16MB arbitrary
$position = 0;
// if handle $fp to file was created, go ahead
if ($fp) {
while(!feof($fp)){
// move pointer to $position in file
fseek($fp, $position);
// take a slice of $chunk_size bytes
$chunk = fread($fp,$chunk_size);
// searching the end of last full text line (or get remaining chunk)
if ( !($last_lf_pos = strrpos($chunk, "\n")) ) $last_lf_pos = mb_strlen($chunk);
// $buffer will contain full lines of text
// starting from $position to $last_lf_pos
$buffer = mb_substr($chunk,0,$last_lf_pos);
////////////////////////////////////////////////////
//// ... DO SOMETHING WITH THIS BUFFER HERE ... ////
////////////////////////////////////////////////////
// Move $position
$position += $last_lf_pos;
// if remaining is less than $chunk_size, make $chunk_size equal remaining
if(($position+$chunk_size) > $filesize) $chunk_size = $filesize-$position;
$buffer = NULL;
}
fclose($fp);
}
使用的内存只有$chunk_size
,速度略低于用 获得的file_ get_contents()
。我认为 PHP Group 应该使用我的方法来优化它的解析功能。
*)在这里找到get_file_size()
函数。