2014-07-01 121 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); 
    }