PHP读取大文本文件日志
php read large text file log
我有一个文本日志文件,大约600 MB。
我想使用php读取它并在html页面上显示数据,但是我只需要在每次运行脚本时添加的最后18行。
由于文件很大,因此无法阅读所有内容,然后按我希望的那样翻转数组。 他们是另一种方式吗?
使用fopen,filesize和fseek打开文件并仅在文件结尾附近开始读取文件。
fseek手册页上的注释包含完整的代码,可读取大文件的最后X行。
- 你可以向后流
$file = popen("tac $filename",'r'); while ($line = fgets($file)) { echo $line; }
- 将该大小的文件加载到内存中可能不是一个好主意。 这样可以解决您的问题。
$file = escapeshellarg($file); $line = 'tail -n 18 '.$file; system($line);
记录下来,遇到了同样的问题,并在这里尝试了所有解决方案。
事实证明,达贡(Dagon)的popen" tac $filename"方式最快,而内存和CPU负载最低。
经过2Gb日志文件测试,每次读取500、1000和2000行。 光滑。 谢谢。
最好的方法是使用fread和fgets逐行读取,这非常快,因为一次只能读取一行而不是while文件:
用法示例为:
$handle = fopen("/logs/log.txt","r")
if ($handle)
{
fseek($handle,-18,SEEK_END); //Seek to the end minus 18 lines
while (!feof($handle))
{
echo fgets($handle, 4096); //Make sure your line is less that 4096, otherwise update
$line++;
}
fclose($handle);
}
<?php
class Test{
//日志路径
const LOG_PATH="E:\phpServer\Apache\logs\error.log";
const NGINX_LOG_PATH="E:\phpServer\\nginx\logs\error.log";
//显示的行数
const PAGES=50;
public static function main(){
header("content-type:text/html;charset=utf-8");
if(!empty($_GET['action'])){
self::$_GET['action']();
exit;
}
}
public static function showApacheLogs(){
$test=new Test();
$result=$test->readLogs(self::LOG_PATH,self::PAGES);
$html="";
foreach($result as $line){
if(strpos($line,"error:")){
$line="<font color='red'>".$line."</font>";
}
$html.="<div class='line'>".$line."<div>";
}
echo $html;
}
public static function showNginxLogs(){
$test=new Test();
$result=$test->readLogs(self::NGINX_LOG_PATH,self::PAGES);
$html="";
foreach($result as $line){
if(strpos($line,"error")){
$line="<font color='red'>".$line."</font>";
}
$html.="<div class='line'>".$line."<div>";
}
echo $html;
}
/**
* 读取日志
*/
private function readLogs($filePath,$num=20){
$fp = fopen($filePath,"r");
$pos = -2;
$eof = "";
$head = false; //当总行数小于Num时,判断是否到第一行了
$lines = array();
while($num>0){
while($eof != "\n"){
if(fseek($fp, $pos, SEEK_END)==0){ //fseek成功返回0,失败返回-1
$eof = fgetc($fp);
$pos--;
}else{ //当到达第一行,行首时,设置$pos失败
fseek($fp,0,SEEK_SET);
$head = true; //到达文件头部,开关打开
break;
}
}
array_unshift($lines,fgets($fp));
if($head){ break; } //这一句,只能放上一句后,因为到文件头后,把第一行读取出来再跳出整个循环
$eof = "";
$num--;
}
fclose($fp);
return array_reverse($lines);
}
}
Test::main();
?>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
.logsBox{
margin:5px;
padding: 5px;
width: 600px;
background: #000;
color:#fff;
font-size: 13px;
float: left;
}
.logsBox .line{
margin: 12px 0;
}
</style>
<div class="logsBox apache">
<div class="line">日志读取...</div>
</div>
<div class="logsBox nginx">
<div class="line">日志读取...</div>
</div>
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
function showLogs(api,showClass){
function readLogs(){
$.ajax({
url:api,
type:"get",
dataType:"text",
success:function(data){
$(showClass).html(data);
}
});
}
readLogs();
setInterval(readLogs,5000);
}
showLogs("?action=showNginxLogs",".nginx");
showLogs("?action=showApacheLogs",".apache");
});
</script>
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。