从多行中解析日志文件以获取相关数据

Parse log files for relevant data from multiple lines

C#、Winforms: 我有一个需要解析的日志文件。此文件包含来自某个程序的交易请求,但该程序跨多行写入交易。

我需要获取 ID# 以及请求是否出于某种原因被处理或拒绝。问题是这些请求在多行上。我唯一的可取之处是它们包含来自记录器的相同时间戳。 (##) 不可用,因为它是一个临时占位符,因此 (19) 可能会在整个日志中重复多次。

我正在考虑扫描 PR_Request,将 ID# 和时间戳作为子字符串,但我不知道如何让流阅读器向下移动到接下来的 4 行并将其写成一个文件中的单行。

示例:

06/10/16 08:09:33.031 (1) PR_Request: IID=caa23b14, 06/10/16 08:09:33.031 (1) PR_Mon: IID=caa23b14, 06/10/16 08:09:33.031 (1) RESUME|BEGIN 06/10/16 08:09:33.031 (1) RESUME_TRIG|SC-TI

06/10/16 08:19:04.384 (19) PR_Request: IID=90dg01b, 06/10/16 08:19:04.384 (19) PR_Mon: IID=90dg01b, 06/10/16 08:19:04.384 (19) RESUME|DENIED: Access not granted.

我需要一个文件的输出在一行中。这样,我就可以用另一个程序解析它并将数据输入数据库。

06/10/16 08:09:33.031 PR_Request: IID=caa23b14 | RESUME | BEGIN | RESUME_TRIG | SC-TI 06/10/16 08:19:04.384 PR_Request: IID=90dg01b | RESUME | DENIED: Access not granted.

编辑:

好的,我想我这里有一个基本代码。它有效,有点。之所以花费这么长时间,是因为当它找到与 PR_Request 的匹配项时,我不得不打开另一个文件流式传输器,然后使用相同的全戳(日期 + 进程号)再次扫描文件。然后它将查找 RESUME|BEGIN 或 RESUME|DENIED,然后写出成功或失败。

有没有什么方法可以通过在最初找到 PR_Request 的地方获取流阅读器行来加快速度,让它从另一行开始,数到 5 行,然后停止它?这将有助于大大加快程序速度。

        string inputfolder = inputloctxt.Text;
        string outputfolder = saveloctxt.Text;
        string outputfile = @"ParsedFile.txt";

        try
        {
            string[] readfromdir = Directory.GetFiles(outputfolder);
            foreach (string readnow in readfromdir)
            {
                using (StreamReader fileread = new StreamReader(readnow))
                {
                    string fileisreading;
                    while ((fileisreading = fileread.ReadLine()) != null)
                    {
                        if (fileisreading.Contains("PR_Request"))
                        {
                            string resumed = null;
                            string fullstamp = fileisreading.Substring(1, 26);
                            string datestamp = fileisreading.Substring(1, 21);
                            string requesttype = fileisreading.Substring(27, 22);
                            string iidnum = fileisreading.Substring(53, 8);
                            using (StreamReader grabnext01 = new StreamReader(readnow))
                            {
                                string grabnow01;
                                while ((grabnow01 = grabnext01.ReadLine()) != null)
                                {
                                    if (grabnow01.Contains(fullstamp))
                                    {
                                        if (grabnow01.Contains("RESUME|BEGIN"))
                                        {
                                            resumed = "TRUE";
                                            break;
                                        }
                                        else if (grabnow01.Contains("RESUME|DENIED"))
                                        {
                                            resumed = "FALSE";
                                            break;
                                        }
                                    }
                                }
                            }
                            File.AppendAllText(outputfolder + outputfile, 
                               datestamp + " " + requesttype + " " + iidnum + " " + resumed + Environment.NewLine);
                            resumed = null;
                        }
                    }
                }
            }
        }

听起来您需要使用 正则表达式 。有一个命名空间 System.Text.RegularExpressions 您可以使用和引用我在示例中为您制作的捕获组。

使用这些网站作为参考:

我为您开始了正则表达式,它不是很漂亮,但应该可以完成工作。

(?:\d{2}\/\d{2}\/\d{2}\s\d{2}\:\d{2}\:\d{2}\.\d{3}\s\(\d+\)\s)(PR_Request: IID=[^,\n]+)(?:\,\n\d{2}\/\d{2}\/\d{2}\s\d{2}\:\d{2}\:\d{2}\.\d{3}\s\(\d+\)\sPR_Mon: IID=[^,\n]*\,\n\d{2}\/\d{2}\/\d{2}\s\d{2}\:\d{2}\:\d{2}\.\d{3}\s\(\d+\)\s)((RESUME|BEGIN|\||DENIED: Access not granted.)*)(?:\n\d{2}\/\d{2}\/\d{2}\s\d{2}\:\d{2}\:\d{2}\.\d{3}\s\(\d+\)\s)*((RESUME_TRIG|SC\-TI|\|)*)