2014-07-01 80 views
0

有日志文件在第3行缺少“新线”,不时阅读TXT文件缺少“新线”

2010.12.17 04:26 127.0.0.1 user:user1 region:NA ERROR: Invalid password 
2010.12.17 04:27 127.0.0.1 user:user1 region:AP ERROR: Invalid password 
2010.12.17 04:32 127.0.0.12010.12.17 04:32 127.0.0.1 user:user1 region:AP ERROR: Invalid password 
2010.12.17 04:32 127.0.0.1 user:user1 region:NA ERROR: Invalid password 

在上面的例子:

2010.12.17 04:32 127.0.0.1应在行

2010.12.17 04:32 127.0.0.1 user:user1 region:AP ERROR: Invalid password应该在另一行。

我需要读取数组中的行,例如file()正在执行,但需要更正的行。

我无法触摸文件本身,通过在需要的位置插入新行来更正它。

我在想fread,但是它会将整个文件内容读入一个字符串。也许我应该解析这个大字符串..?

你有更好的想法如何实现这一目标吗?

+0

该文件有多大?你可以在内存中读取它吗? –

+0

现在它~2mb ..但我有其他文件可能会更大.. – ihtus

回答

2

如果你可以加载整个文件到内存中,您还可以根据什么行的开始看起来像使用preg_split()

$result = preg_split('/(?=\d{4}\.\d{2}\.\d{2})/m', $body); 

print_r($result); // ignore first array element 
+0

谢谢!迄今为止工作。你能解释每一个正则表达式部分吗? – ihtus

0

你必须找到的检测符合这些新行预期的方式,以便您可以读取这些地方的数据。这意味着您需要查看文件行格式,并尝试根据该格式进行阅读。最简单的方法是使用正则表达式,该正则表达式会尝试尽可能多地匹配文本,直到开始下一行的模式。比赛应该考虑线标记结束的可能存在。

幸运的是,日志的每一行都以一个时间戳开始,这个时间戳不应该在文件中变化很大。通常情况下,日志覆盖一天,所以你可以基于你的日志的第一个字符的正则表达式,这必须是第一行的开始。

$file = fopen($logname, "r");  
$content = array(); 
$date = fread($file, 9); // date length 
fseek($file, 0); 
$pattern = $date.".*?(".$date.")?"; 
while ($data = fread($file, 4096)){ 
    $buff .= $data; 
    while (preg_match($pattern, $data,$matches = array())){ 
     $content[] = $matches[0]; 
     $buff = substr($buff, strlen($matches[0])); 
    } 
} // end of file 
if (strlen($buff)){ 
    echo ”extra data at end of log : " . $buff; 
} 

您应该能够根据您的日志时间戳格式调整该代码。

+0

未经测试的代码... – didierc

0

基于Jack的回答,编写了一个使用fopen和fgets的代码:fgets逐行读取,我猜它不会像使用file()或fread()时那样加载内存。

$flog_path="/srv/www/****.log"; 
    $ftemp = fopen($flog_path,"r"); 
    while ($s=fgets($ftemp)) { 
     $elem=preg_split('/(?=\d{4}\.\d{2}\.\d{2})/m', $s); 
     foreach (array_filter($elem) as $v) $result[] = trim($v); 
    }