我有一个包含日志行的日志文件。每一行都由时间戳和消息组成。
timestamp1 blablabla
timestamp2 foo
timestamp3 bar
etc...
我的班级LogFile
有一个地图作为成员,以便将每个时间戳与ifstream位置相匹配
现在我想在这些时间戳上创建一个自定义迭代器。
示例:
LogFile myFile("file.log");
for (LogFile::iterator it = myFile.begin(); it != myFile.end(); it++)
std::cout << it->message << std::endl;
输出:
blablabla
foo
bar
我也希望迭代器能够递减。
现在我真的不知道如何以有效的方式实现它。
最简单的方法是使用每个迭代器增量对文件进行open-seek-read-close。 但这有效吗?我读到open / seek / close非常昂贵。
也许更好的解决方案是使用LogFile::open()
方法打开文件,保持打开状态以执行我们想要的所有增量,最后使用LogFile::close()
方法关闭文件。
你对此有什么建议吗?我确信这不是第一次有人处理这类问题。
编辑更多细节:
我的类LogFile有一个std::map<Time, std::streampos>
类型的成员,用于存储时间戳和流位置之间的链接。
我需要递增和递减迭代器。因此我认为地图会更合适,因为我将使用the std::map::find(Time)
很多(复杂度o(log(n)),而不是std::vector::find(Time)
具有o(n)复杂度。)
日志文件非常大(约20Mo),我的应用程序必须在有限的资源嵌入系统上运行。所以我不能将整个文件存储在ram中,我必须缓冲并只占用我在给定时间内所需的部分。
所以是的,我想我会处理“open()和close()一次”方法。
在增量的情况下,我不必经常std::ifstream::seekg()
。但是在减少的情况下,我没有看到另一种方法来寻找每个时间戳。这真的是最好的方式吗?
答案 0 :(得分:0)
除非必要,否则我肯定会避免打开和关闭文件。在LogFile
构造函数中打开文件,在析构函数中将其关闭。
答案 1 :(得分:0)
我不知道您的确切用例,但在我看来,使用map来存储这些数据似乎是多余的。我认为你不会使用确切的时间戳来查询这张地图,不是吗?并且我假设日志文件条目已经在源日志文件中按时间排序,因此当读入向量时,它们也将被排序。我的建议是这样,使用包含时间戳和ifstream位置对的向量。
只要使用该文件的LogFile实例存在,我肯定会建议保持文件处于打开状态。这样,当有人使用迭代器按顺序访问条目时,您将节省大量时间,因为搜索次数会减少。
如果日志文件不是太大,我还建议将文件中的所有条目读取到内存中,这样可以节省所有i / o操作丢失的时间。
答案 2 :(得分:0)
可能值得尝试使用mmap
映射文件,然后使用madvise
手动制作可能会很快访问的网页,并保留在内存中。