使用多行条目解析日志文件

时间:2013-10-14 14:32:20

标签: c++ c winapi

我正在从第三方应用程序解析合理大小的日志文件(最多50Mb,此时它包装),以便检测在指定时间范围内发生的KEY_STRING。此日志文件中的典型条目可能如下所示

DEBUG 2013-10-11@14:23:49 [PID] - Product.Version.Module
(Param 1=blahblah Param2=blahblah Param3 =blahblah
Method=funtionname)
String that we usually don't care about but may be KEY_STRING  

条目以空行分隔(\ r \ n在条目末尾,然后\ r \ n开始下一个条目之前)

这是针对Windows特定的实现,因此不需要是可移植的,可以是C / C ++ / Win32

逐行读取这一行将非常耗时,但其优点是能够解析时间戳并检查条目是否在给定的时间范围内,然后再检查条目中是否存在任何KEY_STRING。如果我通过块读取文件,我可能会找到KEY_STRING,但块没有更早的时间戳,或者块边界甚至可能在KEY_STRING的中间。将整个文件读入内存并解析它不是一个选项,因为应用程序这是一个当前具有相对较小的占用空间的一部分,因此无法证明将此增加大约10倍仅用于解析文件(甚至是暂时的) 。有没有办法可以通过分隔块(特别是“\ r \ n \ r \ n”)来读取文件?还是有其他/更好的方法我没有想过?

对此的任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:0)

  1. 确保你不能使用记忆,也许你有点太“偏执”了?过早优化,以及所有这些。
  2. 逐行读取(因为这样可以更容易地分隔条目),但是使用缓冲读取包装行读取,一次读取尽可能多的读取,可能是1 MB。这样可以最大限度地减少磁盘I / O,这通常有助于提高性能。

答案 1 :(得分:0)

假设(通常情况下)文件中的所有条目按时间顺序排列,您应该能够使用二进制搜索的变体来查找正确的起点和终点,然后解析数据介于两者之间。

基本的想法是寻找文件的中间位置,然后阅读几行,直到你找到以“DEBUG”开头的那一行,然后读取时间戳。如果它早于您关心的时间,请寻求3/4 ths 标记。如果晚于你关心的时间,请回到1/4 th 。标记。重复基本想法,直到找到开头。然后在结束时做同样的事情。

一旦您寻求的数量下降到某个阈值(例如,64K)以下,寻找到64K对齐块的开头可能会更快,并且继续向前读取而不是再寻求

另一种可能的考虑因素是,您是否可以在后台进行一些工作来构建文件的索引作为其修改,然后在实际需要结果时使用索引。索引将(例如)在其写入之后立即读取每个条目的时间戳(例如,在修改日志文件时使用ReadDirectoryChangesW来告知)。它会将文本时间戳转换为例如time_t,然后在索引中存储一个条目,给出该条目的time_t和文件偏移量。这应该足够小(对于50兆字节的日志文件可能在一兆字节以下),以便在内存中完全使用它。

答案 2 :(得分:0)

一种可能的解决方案是使用内存映射文件。我个人从未将它们用于除玩具应用之外的任何东西,但我知道它背后的一些理论。

基本上,它们提供了一种访问文件内容的方式,就好像它们是内存一样,我相信它的行为方式与虚拟内存类似,因此所需的部分将根据需要进行分页,并逐页输出在某些时候(你应该阅读文档来制定这背后的规则)。

在伪代码中(因为我们都喜欢伪代码),你会沿着这些方向做点什么:

HANDLE file = CreateFile(...);
HANDLE file_map = CreateFileMapping(file, 0, PAGE_READONLY, 0, 0, ...);
LPVOID mem = MapViewOfFile(file_map, FILE_MAP_READ, 0, 0, 0);

// at this point you can use mem to access data in the mapped part of the file...
// for your code, you would perform parsing as if you'd read the file into RAM.

// when you're done, unmap and close the file:
UnmapViewOfFile(mem);
CloseHandle(file_map);
CloseHandle(file);

我现在道歉,因为没有提供最优秀的建议,而是encourage further reading - Windows提供了许多处理内存的功能,而且最值得一读。

相关问题