从文本文件中提取某些行的最有效方法

时间:2013-03-06 17:07:39

标签: c++ ifstream

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

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

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

关键点:

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

NB。 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 个答案:

答案 0 :(得分: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很慢。如果你没有获得足够的性能,你可以考虑用FILE *或mmap替换fstream。

答案 1 :(得分: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

答案 2 :(得分:0)

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

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

添加:

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

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

我将发布一些我在其他地方发布的“快速读取文件”的基准测试。但请记住,您正在阅读的硬盘将是大部分时间。

参考文献:

getline while reading a file vs reading whole file and then splitting based on newline character

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

What is the best efficient way to read millions of integers separated by lines from text file in c++

答案 3 :(得分:0)

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

您必须阅读文本才能进行搜索,因此您可以尽可能多地阅读该文件。

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

一旦文件在内存中,搜索技术可能会有微不足道的性能提升。