簡體   English   中英

讀取日志文件,然后拉出帶有特定文本的行

[英]Read a Log file and pull out lines with specific text

我有一個不斷添加的日志(例如每秒1-5行或更多),文件可能會變得很大20MB +

示例日志文件:

[Wed Aug 26 00:01:48 2015] You try to kick a snake, but miss!
[Wed Aug 26 00:01:50 2015] A snake hits YOU for 3 points of damage.
[Wed Aug 26 00:01:51 2015] You punch a snake for 6 points of damage.
[Wed Aug 26 00:01:51 2015] A decaying skeleton tries to hit Clumsy, but misses!
[Wed Aug 26 00:01:53 2015] A snake hits YOU for 1 point of damage.
[Wed Aug 26 00:01:53 2015] A decaying skeleton tries to hit Clumsy, but misses!
[Wed Aug 26 00:01:54 2015] You gain experience!!
[Wed Aug 26 00:01:54 2015] You punch a snake for 6 points of damage.
[Wed Aug 26 00:01:54 2015] You have slain a snake!
[Wed Aug 26 00:01:56 2015] --You have looted a Snake Egg.--
[Wed Aug 26 00:01:56 2015] A decaying skeleton tries to hit Clumsy, but misses!
[Wed Aug 26 00:01:57 2015] --You have decided to not loot 2 item(s): Snake Fang. The item(s) will be available to anyone after the corpse(s) unlock.--
[Wed Aug 26 00:01:57 2015] --You have decided to not loot 2 item(s): Snake Scales. The item(s) will be available to anyone after the corpse(s) unlock.--
[Wed Aug 26 00:01:59 2015] a decaying skeleton's corpse splinters into hundreds of tiny bone fragments.
[Wed Aug 26 00:01:59 2015] Clumsy crushes a decaying skeleton for 7 points of damage.
[Wed Aug 26 00:01:59 2015] a decaying skeleton has been slain by Clumsy!
[Wed Aug 26 00:01:59 2015] Auto attack is on.
[Wed Aug 26 00:02:00 2015] Grug tells General:2, 'LFM AM/LORD'
[Wed Aug 26 00:02:00 2015] You punch a large rat for 5 points of damage.
[Wed Aug 26 00:02:00 2015] A large rat bites YOU for 1 point of damage.
[Wed Aug 26 00:02:00 2015] You kick a large rat for 1 point of damage.
[Wed Aug 26 00:02:02 2015] You punch a large rat for 2 points of damage.
[Wed Aug 26 00:02:03 2015] A large rat tries to bite YOU, but misses!
[Wed Aug 26 00:02:06 2015] You punch a large rat for 6 points of damage.
[Wed Aug 26 00:02:06 2015] A large rat bites YOU for 1 point of damage.
[Wed Aug 26 00:02:08 2015] a decaying skeleton clatters as it turns towards you.
[Wed Aug 26 00:02:08 2015] <SYSTEMWIDE_MESSAGE>: Gorenaire has been defeated by a group of hardy adventurers! Please join us in congratulating Kyrax along with everyone else who participated in this achievement!
[Wed Aug 26 00:02:08 2015] Clumsy tries to crush a decaying skeleton, but misses!
[Wed Aug 26 00:02:08 2015] A decaying skeleton tries to hit Clumsy, but misses!
[Wed Aug 26 00:02:09 2015] A large rat tries to bite YOU, but YOU dodge!
[Wed Aug 26 00:02:09 2015] You try to punch a large rat, but miss!
[Wed Aug 26 00:02:11 2015] Clumsy crushes a decaying skeleton for 8 points of damage.
[Wed Aug 26 00:02:11 2015] A decaying skeleton hits Clumsy for 2 points of damage.
[Wed Aug 26 00:02:11 2015] You kick a large rat for 1 point of damage.
[Wed Aug 26 00:02:12 2015] A large rat bites YOU for 1 point of damage.
[Wed Aug 26 00:02:13 2015] You gain experience!!
[Wed Aug 26 00:02:13 2015] You punch a large rat for 6 points of damage.
[Wed Aug 26 00:02:13 2015] You have slain a large rat!
[Wed Aug 26 00:02:13 2015] Clumsy crushes a decaying skeleton for 8 points of damage.
[Wed Aug 26 00:02:14 2015] A decaying skeleton hits Clumsy for 3 points of damage.
[Wed Aug 26 00:02:15 2015] --You have decided to not loot 1 item(s): Piece of Rat Fur. The item(s) will be available to anyone after the corpse(s) unlock.--
[Wed Aug 26 00:02:15 2015] --You have decided to not loot 2 item(s): Rat Whiskers. The item(s) will be available to anyone after the corpse(s) unlock.--
[Wed Aug 26 00:02:16 2015] a decaying skeleton's corpse splinters into hundreds of tiny bone fragments.
[Wed Aug 26 00:02:18 2015] Auto attack is on.
[Wed Aug 26 00:02:18 2015] a snake hisses and strikes!
[Wed Aug 26 00:02:18 2015] You punch a snake for 6 points of damage.
[Wed Aug 26 00:02:18 2015] A snake tries to hit YOU, but misses!
[Wed Aug 26 00:02:20 2015] You kick a snake for 1 point of damage.
[Wed Aug 26 00:02:21 2015] You try to punch a snake, but miss!
[Wed Aug 26 00:02:21 2015] A snake hits YOU for 4 points of damage.
[Wed Aug 26 00:02:24 2015] A snake tries to hit YOU, but misses!
[Wed Aug 26 00:02:25 2015] You try to punch a snake, but a snake parries!
[Wed Aug 26 00:02:27 2015] A snake tries to hit YOU, but misses!
[Wed Aug 26 00:02:28 2015] You kick a snake for 1 point of damage.
[Wed Aug 26 00:02:28 2015] You try to punch a snake, but miss!
[Wed Aug 26 00:02:30 2015] A snake hits YOU for 2 points of damage.
[Wed Aug 26 00:02:32 2015] You try to punch a snake, but miss!
[Wed Aug 26 00:02:33 2015] A snake tries to hit YOU, but misses!
[Wed Aug 26 00:02:36 2015] You punch a snake for 5 points of damage.
[Wed Aug 26 00:02:36 2015] A snake hits YOU for 1 point of damage.
[Wed Aug 26 00:02:37 2015] You kick a snake for 1 point of damage.
[Wed Aug 26 00:02:39 2015] A snake hits YOU for 1 point of damage.
[Wed Aug 26 00:02:40 2015] You gain experience!!
[Wed Aug 26 00:02:40 2015] You punch a snake for 6 points of damage.
[Wed Aug 26 00:02:40 2015] You have slain a snake!
[Wed Aug 26 00:02:42 2015] --You have looted a Snake Egg.--
[Wed Aug 26 00:02:42 2015] <SYSTEMWIDE_MESSAGE>: Innoruuk has been defeated by a group of hardy adventurers! Please join us in congratulating Harken along with everyone else who participated in this achievement!
[Wed Aug 26 00:02:43 2015] --You have decided to not loot 1 item(s): Snake Scales. The item(s) will be available to anyone after the corpse(s) unlock.--
[Wed Aug 26 00:02:46 2015] Auto attack is on.
[Wed Aug 26 00:02:46 2015] You punch a large rat for 6 points of damage.
[Wed Aug 26 00:02:46 2015] A large rat tries to bite YOU, but misses!
[Wed Aug 26 00:02:47 2015] You try to kick a large rat, but miss!
[Wed Aug 26 00:02:47 2015] You punch a large rat for 6 points of damage.
[Wed Aug 26 00:02:49 2015] A large rat bites YOU for 1 point of damage.
[Wed Aug 26 00:02:51 2015] You gain experience!!
[Wed Aug 26 00:02:51 2015] You punch a large rat for 5 points of damage.
[Wed Aug 26 00:02:51 2015] You have slain a large rat!
[Wed Aug 26 00:02:53 2015] --You have decided to not loot 1 item(s): Piece of Rat Fur. The item(s) will be available to anyone after the corpse(s) unlock.--
[Wed Aug 26 00:02:53 2015] --You have decided to not loot 2 item(s): Scalded Rat Skin. The item(s) will be available to anyone after the corpse(s) unlock.--
[Wed Aug 26 00:02:56 2015] Auto attack is on.
[Wed Aug 26 00:02:56 2015] You try to punch a large rat, but miss!
[Wed Aug 26 00:02:56 2015] A large rat bites YOU for 1 point of damage.
[Wed Aug 26 00:02:57 2015] You kick a large rat for 1 point of damage.

我將日志文件的路徑和名稱存儲在程序的設置中,如下所示:

Properties.Settings.Default.setting_logfolder // Folder Path
Properties.Settings.Default.setting_logfile // File Name

我需要在單擊按鈕時打開文件並讀取文件,直到再次單擊按鈕以停止該過程為止,而在讀取文件時,我需要將找到的行輸出到文本框以顯示給用戶。 在這種情況下,日志文件仍將由父程序寫入。

這是到目前為止的按鈕代碼。

    private void btnStart_Click(object sender, EventArgs e)
    {
        if (btnStart.Text == "Start Parsing")
        {
            // change text on button and switch status image
            btnStart.Text = "Stop Parsing";
            pbStatus.Image = Properties.Resources.online;

            string logfile = Properties.Settings.Default.setting_logfolder += Properties.Settings.Default.setting_logfile;

            if (File.Exists(logfile))
            {
                Stream stream = File.Open(logfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                StreamReader streamReader = new StreamReader(stream);
                string str = streamReader.ReadToEnd();
                tbOutput.AppendText(str);
                streamReader.Close();
                stream.Close();
            }
            else
            {
                tbOutput.AppendText(logfile);
            }
        }
        else
        {
            btnStart.Text = "Start Parsing";
            pbStatus.Image = Properties.Resources.offline;
        }
    }

我需要它來繼續讀取文件,直到再次按下按鈕為止,而我只需要從文件中讀取這樣的行

[Wed Aug 26 00:02:08 2015] <SYSTEMWIDE_MESSAGE>: XXXXXXXXX has been defeated by a group of hardy adventurers! Please join us in congratulating XXXXXX along with everyone else who participated in this achievement!

我的回答“對於C#”

要查找包含系統范圍消息的任何行,請使用:

\[[\w :]+\] <SYSTEMWIDE_MESSAGE>

對於該消息,但允許使用不同的名稱,請使用:

\[[\w :]+\] <SYSTEMWIDE_MESSAGE>: \w+ has been defeated by a group of hardy adventurers! Please join us in congratulating \w+ along with everyone else who participated in this achievement!

這些都假定用戶/字符名稱可以有字母,數字或下划線

您當前的算法執行ReadToEnd() ,它不會讀取單個行並一次咳嗽一行,這似乎是您想要的(?!也許!! ??!)。 相反,它將讀取到流(文件)的末尾,然后咳出整個文件。

對一個相關問題的答案中,簡要介紹了使用FileSystemWatcher的方法-FileSystemWatcher有一些警告,但應該是更“純凈的.Net方法”

替代解決方案(Powershell)

如果您不需要GUI,而只想將這些信息顯示在屏幕上以便可以對其進行處理,那么快速而又骯臟的解決方案實際上就是PowerShell領域中的一行。 打開一個PowerShell提示符(或創建一個腳本),然后(假設我們使用的是一個幽默的名為chase.dat的日志文件和一個選定的正則表達式而不是<#regex#> ,請使用以下代碼:

cat chase.dat -tail 1 -wait | ?{$_ -match '<#regex#>'}

將適當的正則表達式替換為<#regex#>並將文件名替換為chase.dat ,它將在寫入文件時吐出與您的正則表達式匹配的所有新行。 如果您有興趣,我可以解釋一下...

GUI!

如果確實要結合使用GUI和PowerShell,則上面的PS腳本行將傳遞到本文概述的類中的“ PipelineExecutor ”構造函數,然后,只要腳本返回,該構造函數就會更新指定的屬性(例如TextBox.Text )。更多(在這種情況下為已過濾)文本。

只是這樣做,它就像一個魅力!

這是使用FileWatcher類的一種簡單方法

 public static Watchfile() 
 {
         FileSystemWatcher watch = new FileSystemWatcher();
         watch.Path = @"C:\";
         watch.Filter = "log.txt";
         watch.NotifyFilter = NotifyFilters.LastAccess |    
         NotifyFilters.LastWrite; 

        watch.Changed += new FileSystemEventHandler(OnChanged);
       watch.EnableRaisingEvents = true;
  }


 private static void OnChanged(object source, FileSystemEventArgs e)
 {


    string line;
         if (e.FullPath == @"C:\log.txt")
         {
             Regex _regex = new Regex(@"\[[\w :]+\] <SYSTEMWIDE_MESSAGE>: \w+ has been defeated by a group of hardy adventurers! Please join us in congratulating \w+ along with everyone else who participated in this achievement!");
             System.IO.StreamReader file =
                       new System.IO.StreamReader(@"C:\log.txt");

             while ((line = file.ReadLine()) != null)
             {
                 Match match = _regex.Match(line);
                 if (match.Success)
                 {

                     //Match Found

                 }


             }

             file.Close();
         }


 }

好的,所以首先,如果您要解析的日志文件可能太大而無法保存在內存中(通常大多數時間不是20mb),請使用File.OpenText並以塊形式讀取它或線。 這意味着您不需要將整個文本文件加載到內存中。 其次,我將讀取邏輯移到它自己的類或函數中。 如果您正在運行Windows Forms或WPF,並且希望在找到行時按原樣更新UI,那么您將需要在單獨的線程/任務上進行此讀取,以使UI進行更新而不鎖定它。 使用Dispatcher類從后台任務更新您的UI。

然后,您的正則表達式將需要基於要捕獲的精確行。 在我看來,您可以忽略一行開頭的方括號中的所有內容,然后斷言:

\\w+ has been defeated by a group of hardy adventurers! Please join us in congratulating \\w+ along with everyone else who participated in this achievement!$

編輯:

從文件共享選項看,日志文件可能正在增長? 如果正確,請避免逐行讀取,因為您可以讀取部分行。 如果您要在流中緩存位置,則可能意味着您失去了潛在的比賽機會。 相反,請讀取一個塊,檢查Environment.NewLine ,並將其解析為正則表達式引擎中的一行。

嘗試這個:

-using (var fileStream = new FileStream("YOUR FILE", FileMode.Open, FileAccess.Read, FileShare.None))
{                  
    using (var streamReader = new StreamReader(fileStream))
    {
        string line;
        while((line = reader.ReadLine()) != null)
        {
          if(line == "YOUR TEXT")
          {
           // Do the rest
          }
        }
    }
}

您必須指定特定的模式才能完成此示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM