分析包含多行条目的日志文件
Parsing log file with multi-line entries
我正在努力从第三方应用程序解析一个合理大小的日志文件(最多 50Mb,此时它包装),以检测在指定时间范围内发生的KEY_STRINGs。此日志文件中的典型条目可能如下所示
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 在条目末尾,\r 在下一个条目开始之前)
这是针对Windows特定的实现,因此不需要可移植,并且可以是C/C++/Win32
逐行读取此内容将非常耗时,但具有能够解析时间戳并检查条目是否在给定时间范围内的好处,然后再检查条目中是否存在任何KEY_STRINGs。如果我按块读取文件,我可能会找到一个KEY_STRING但块没有更早的时间戳,或者块边框甚至可能在KEY_STRING的中间。将整个文件读入内存并解析它不是一种选择,因为当前要成为其中一部分的应用程序占用空间相对较小,因此不能证明仅仅为了解析文件而将其增加 ~10 倍(即使是暂时的)。有没有办法通过分隔块(特别是"\r\r")来读取文件?还是没有我想到的另一种/更好的方法?
任何这方面的帮助将不胜感激!
一种可能的解决方案是使用内存映射文件。我个人从未将它们用于玩具应用以外的任何东西,但知道它背后的一些理论。
从本质上讲,它们提供了一种访问文件内容的方法,就好像它们是内存一样,我相信它们的行为方式与虚拟内存类似,因此所需的部分将根据需要分页,并在某个时候分页(您应该阅读文档以制定其背后的规则)。
在伪代码中(因为我们都喜欢伪代码),你会按照以下思路做一些事情:
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);
我现在很抱歉没有提供最优秀的建议,而是鼓励进一步阅读 - Windows提供了许多功能来处理您的内存,并且非常值得一读。
- 确保你不能使用记忆,也许你有点太"偏执"了?过早优化等等。
- 逐行读取(因为这样可以更轻松地分隔条目),但用缓冲读取来包装行读取,一次读取尽可能多的内容,也许是 1 MB。这样可以最大程度地减少磁盘 I/O,这通常有利于提高性能。
假设(通常情况下)文件中的所有条目都按时间排序,您应该能够使用二分搜索的变体来查找正确的起点和终点,然后解析两者之间的数据。
基本思想是寻找文件的中间,然后读取几行,直到你到达以"DEBUG"开头的行,然后读取时间戳。如果它早于你关心的时间,请向前寻找 3/4 标记。如果晚于你关心的时间,请回到1/4th。马克。重复基本想法,直到找到开始。然后在末世做同样的事情。
一旦您搜索的数量低于某个阈值(例如,64K),那么寻找 64K 对齐块的开头可能会更快,然后从那里继续向前读取而不是再进行任何搜索。
另一种需要考虑的可能性是,您是否可以在后台执行一些工作,以便在修改文件时构建文件的索引,然后在实际需要结果时使用索引。例如,索引将在写入条目后立即读取每个条目的时间戳(例如,使用ReadDirectoryChangesW
在日志文件被修改时被告知)。例如,它会将文本时间戳转换为time_t,然后在索引中存储一个条目,提供该条目的time_t和文件偏移量。这应该足够小(对于 50 MB 的日志文件可能低于 1 兆字节),以便完全在内存中使用它很容易。
- 加快在C++中读取/处理日志文件的速度
- 如何将消息时间戳写入日志文件?
- 分析包含 NMEA 句子的日志文件C++
- 如何从日志文件中抓取状态代码?(在 C++ 中)
- 未创建日志文件
- 尝试使用 EvtSetChannelConfigProperty() 函数更新最大事件日志文件大小时插入的错误值
- 提升日志:文件轮换
- POSIX C/C++日志文件(VEX V5 Brain)
- boost日志文件无法创建sample.log文件
- 哪个更适合从C++写入敏感的日志文件,在文件描述符上写()或文件上的fprintf()?
- 如何编写日志文件,以便可以使用记事本实时读取它以进行C++
- 如何在QT中使用DEBUG对齐日志文件中的数据?
- Qt - 如何在 30 天后删除日志文件,文件名不固定
- Mac OS X:应用程序可以创建日志文件
- 将断言消息写入日志文件
- 检查日志文件以找出 vcredist.exe 安装失败的原因
- C++同时记录到控制台和日志文件
- 无法创建将包含日志文件的文件夹
- (罗)如何使用相对路径保存日志文件
- boost::log关闭日志文件并打开一个新文件