PHP实现读取一个1G的文件大小。
要求如下:有一个大约1G的现有日志文件,大约5000000行,最后几行的内容用PHP返回。1。直接使用文件函数操作或file_get_content()阳性的内存溢出
注意:由于文件功能是一次性的所有内容读入内存,和PHP为了防止一些写坏的程序占用内存太多所造成的系统内存,服务器宕机,那么默认的限制只能使用16M的内存,这是php.ini在memory_limit = 16M到集。如果将此值设置为- 1,则内存使用不受限制。
下面是使用文件删除文件最后一行的代码的一部分。
复制代码代码如下所示:
ini_set('memory_limit ',' 1 ');
文件大小= 'access日志;
数据=文件($文件);
$ = $数据{计数($数据)- 1 };2。直接调用Linux的尾部命令来显示最后一行
Linux命令行下,你可以使用尾N 10 access.log直接显示日志文件的最后一行很容易。您可以使用PHP直接调用尾部命令,并按照如下方式执行PHP代码。
复制代码代码如下所示:
'access日志文件;
文件大小= escapeshellarg(文件); / /安全撤离的命令行参数
$行=尾n 1 $文件;
回声$线;3。直接使用PHP的fseek文件操作
这是最常见的方式,它不需要把文件的内容读入内存,而是直接通过指针操作,所以效率相当高。在fseek文件操作,有几种不同的方法,效率可能略有不同,这是常见的两种方法。
方法1:
首先通过fseek找到最后一个EOF文件,然后找到的最后一行的起始位置,将这行数据,为及时发现的起始位置,然后对线的位置,等等,直到你找到为民行。
复制代码代码如下所示:
函数尾($ FP,$ n,$基= 5)
{
断言($ > 0);
$ = $ n + 1;
行=数组();
同时(计数($行)< $ = n){
尝试{
fseek($ FP,至POS,seek_end);
} catch(异常E){
Fseek(0);
打破;
}
美元=基础;
而(!Feof($ FP)){
array_unshift(合线、fgets($ FP));
}
}
返回array_slice(合线,0,$ N);
}
var_dump(尾(fopen(访问日志。
方法二:
或使用fseek的路终于开始从文件读取,但这不是读,而是一块读书,读一个数据块,它会读一个缓冲区的数据,后跟一个换行符()以确定在$数数据之后最多读取的数量。
实现代码如下所示
复制代码代码如下所示:
$ FP = fopen(文件,R);
$ = 10;
$ = 2;
$;
= $ ;
当($行> 0){
虽然(美元)!= {)
fseek(fp美元美元,POS,seek_end);
$ T =指针($ FP);
百万美元—;
}
$;
$data = fgets($ FP);
$线—;
}
Fclose($ FP);
回波数据方法三:
复制代码代码如下所示:
$ FP = fopen(文件,R);
$ = 10;
$块= 4096;
FS = sprintf($ % U
为最大值=(intval($ FS)= = php_int_max)php_int_max:文件大小(文件);
为($ = 0;
seeksize美元=(最大长度>美元美元美元美元美元一块):最大至len;
fseek($ FP,(($ len + $ seeksize)* 1,seek_end);
readdata美元= fread($ FP,seeksize美元)。readdata美元;
If (substr_count ($readData, > > $ = 1){
preg_match(!(**{。(元)。} $!
$ =匹配{ 0 };
打破;
}
}
Fclose($ FP);
回波数据;