从多行中解析日志文件以获取相关数据
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|\|)*)
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|\|)*)