0

我有一个可变长度的日志文件,它可能包含也可能不包含我正在寻找的字符串。

行有时间戳等,后跟 < 参数 >#< 值 > 我想检查参数并提取值。

下面的实现有效,但我确信必须有一种更有效的方法来解析文件。

关键点:

  • 大多数行将被忽略
  • 大约有 1600 个日志文件,大小在 1 - 20 Mb 之间
  • 即使每个文件的小幅收益也将是一个优势

注意。parse 函数调用 substring 然后将其转换为 int

任何想法都非常感谢

ifstream fileReader(logfile.c_str());
string lineIn;
if(fileReader.is_open())
{

while(fileReader.good())
{
    getline(fileReader,lineIn);

    if(lineIn.find("value1#") != string::npos)
    {
        parseValue1(lineIn);
    }
    else if(lineIn.find("value2#") != string::npos)
    {
        parseValue2(lineIn);
    }
    else if(lineIn.find("value3#") != string::npos)
    {
        parseValue3(lineIn);
    }   
}
}
fileReader.close();
4

4 回答 4

1

首先你做错了循环。你的代码应该是:

while( getline( fileReader,lineIn ) ) {
}

二、线路:

if( fileReader.is_open() )

fileReader.close();

是多余的。至于速度。我建议使用正则表达式:

std::regex reg ( "(value1#)|(value#2)|(value#3)(\\d+)" );
while( getline( fileReader,lineIn ) ) {
    std::smatch m;
    if( std::regex_search( lineIn.begin(), lineIn.end(), m, reg ) ) {
        std::cout << "found: " << m[4] << std::endl;
    } 
}

当然,您需要相应地修改正则表达式。

不幸的是,众所周知,iostream 非常慢。如果您无法获得足够的性能,您可以考虑将 fstream 替换为 FILE * 或 mmap。

于 2013-03-06T17:28:58.063 回答
0

您的执行瓶颈将在文件 I/O 中。
我建议您一次提取尽可能多的数据到缓冲区中。接下来,在缓冲区中搜索您的令牌。

您必须阅读文本才能搜索它,因此您最好尽可能多地阅读文件。

将太多数据读入内存可能会有一些缺点。如果操作系统无法容纳所有数据,它可能会将其分页到硬盘驱动器,这使得该技术毫无价值(除非您希望操作系统处理以块的形式读取文件)。

一旦文件在内存中,搜索技术的性能提升可能可以忽略不计。

于 2013-03-06T19:22:06.603 回答
0

看起来在同一个字符串中有很多重复的搜索,效率不会很高。

以正确的方式解析文件/行。

Boost 中有三个库可能会有所帮助。

使用正则表达式解析该行:http: //www.boost.org/doc/libs/1_53_0/libs/regex/doc/html/index.html

使用标记器 http://www.boost.org/doc/libs/1_53_0/libs/tokenizer/index.html

对于完全自定义,您始终可以使用 Spirit。 http://www.boost.org/doc/libs/1_53_0/libs/spirit/doc/html/index.html

于 2013-03-06T17:19:32.293 回答
0

第一步是弄清楚在输入文件中花费了多少时间if(lineIn.find(...)...以及实际读取输入文件的时间有多少。

应用程序运行的时间(您可能希望选择一些日志文件,而不是全部)。您可能希望连续运行几次以查看您获得相同(大约)的值。

添加:

#if 0
if (lineIn.find(...) ...) 
...
#endif

并比较所需的时间。我的猜测是它实际上不会有太大的不同。但是,如果搜索是时间的主要组成部分,您可能会发现使用更聪明的搜索方法是有益的。有一些非常聪明的方法可以在较大的字符串中搜索字符串。

我将发布一些我在其他地方发布的“更快地读取文件”的基准。但请记住,您正在读取的硬盘将是主要的时间量。

参考:

读取文件时获取行与读取整个文件然后根据换行符拆分

稍微不那么相关,但也许很有趣:

在c ++中从文本文件中读取数百万行分隔的整数的最佳有效方法是什么

于 2013-03-06T17:20:50.080 回答