提升:如何在巨大的文本文件中找到迭代器的位置?

时间:2011-03-15 18:35:38

标签: regex boost text iterator

我正在使用boost :: regex来匹配巨大文本文件(大于200 MB)内的某些模式的程序。匹配工作正常,但是为了构建输出文件,我需要按照文本中找到的顺序对匹配(只有2,但是在所有文本上)进行排序。 好吧,当处于调试模式时,在cout过程中,我可以在迭代器 it1 里面看到一个 m_base 属性,该属性显示了循环每一步增加的地址,我认为这个m_base地址是文本中匹配模式的地址,但我无法证明它,我找不到访问该属性来存储地址的方法。 我不知道是否有办法检索文本中每个匹配模式的地址,但我真的需要获取这些信息。

#define FILENAME "File.txt"
int main() { 

    int length;     
    char * cMainBuf;
    ifstream is;
    is.open (FILENAME, ios::binary );

    is.seekg(0, ios::end);
    length = is.tellg();
    is.seekg (0, ios::beg);

    cMainBuf = new char[length+1];
    memset(cMainBuf, '\0',length+1);

    is.read(cMainBuf,length);
    is.close();
    string str=cMainBuf;
    regex reg("^(\\d{1,3}\\s[A-F]{99})");
    regex rReg(reg);
    int const sub_matches[] = { 1 };
    boost::sregex_token_iterator it1(str.begin() ,str.end() ,rReg ,sub_matches ), it2; 
    while(it1!=it2) 
    { 
        cout<<"#"<<sz++<<"- "<< *(it1++) << endl;
    }
    return 0;
}

@sln 嗨sln, 我会回答你的问题: 1.我删除了所有不属于此问题的代码,因此有些库仍在那里; 2.与1相同; 3.因为文件实际上不是一个简单的文本文件,它可以有任何符号,它可能会影响阅读过程,正如我过去所能想到的那样; 4.在测试期间需要零缓冲,因为我无法在缓冲区中存储超过1MB的空间; 5.迭代器也不能使用char *来设置文件的开头和结尾,因此必须将其更改为字符串; 6.传入的RegEx不会被声明为静态,这只是一个表示问题的草稿和锚点行为来查找行开头,而不仅仅是字符串的开始; 7. sub_matches是测试的一部分,用于查看迭代器在其中包含2个或更多组的正则表达式的位置; 8. sz只是一个柜台; 9. const std :: _ St​​ring_const_iterator&lt; _Elem,_Traits,_Alloc&gt;很久。

实际上所有代码都工作正常,我可以识别文本中的任何模式,但我真正需要知道的是每个匹配模式的内存地址(在这种情况下,每次迭代的迭代器的地址)。我可以意识到m_base有这个地址,但直到现在我才能检索到这个地址。 我继续分析,如果我找到任何解决这个问题的方法,我会在这里发布。

1 个答案:

答案 0 :(得分:1)

编辑 @Tchesko,我正在删除原来的答案。我已经加载了boost :: regex并使用regex_search()进行了尝试。它不是你正在做的itr1方法,但我认为它归结为只是从boost :: smatch类获得结果,这实际上是boost :: match_results()。

它有成员函数来获取匹配和子匹配的位置和长度。所以,它真的只需要找到你的大字符串的偏移量。你无法访问m_base的原因是它是一个私有成员变量。

使用方法position()和length()。请参阅下面的示例...我运行,调试和测试。我再次回到VS-2005的速度。但是,提升似乎有点古怪。如果我要使用它,我希望它做Unicode,而不是意味着我必须编译ICU。我正在使用的增强二进制文件已下载1.44。最新版本是1.46.1,所以我可以在用ICU评估其生存能力后用vc ++ 8构建它。

嘿,让我知道结果如何。祝你好运!

#include <boost/regex.hpp> 
#include <locale> 
#include <iostream> 

using namespace std;

int main() 
{ 
  std::locale::global(std::locale("German")); 
  std::string s = "  Boris  Schäling   "; 
  boost::regex expr("(\\w+)\\s*(\\w+)"); 
  boost::smatch what; 
  if (boost::regex_search(s, what, expr)) 
  { 
      // These are from boost::match_results() class ..
      int Smpos0 = what.position();
      int Smlen0 = what.length();
      int Smpos1 = what.position(1);
      int Smlen1 = what.length(1);
      int Smpos2 = what.position(2);
      int Smlen2 = what.length(2);

      printf ("Match Results\n--------------\n");
      printf ("match  start/end  = %d - %d,  length = %d\n", Smpos0, Smpos0 + Smlen0,  Smlen0);
      std::cout << "  '" << what[0] << "'\n" << std::endl; 
      printf ("group1 start/end  = %d - %d,  length = %d\n", Smpos1, Smpos1 + Smlen1, Smlen1);
      std::cout << "  '" << what[1] << "'\n" << std::endl; 
      printf ("group2 start/end  = %d - %d,  length = %d\n", Smpos2, Smpos2 + Smlen2, Smlen2);
      std::cout << "  '" << what[2] << "'\n" << std::endl;

/*
    This is the hard way, still m_base is a private member variable.
    Without m_base, you can't get the root address of the buffer.

    long Match_start = (long)(what[0].first._Myptr);
    long Match_end   = (long)(what[0].second._Myptr);
    long Grp1_start  = (long)(what[1].first._Myptr);
    long Grp1_end    = (long)(what[1].second._Myptr);
*/
  } 
} 

/* Output:
Match Results
--------------
match  start/end  = 2 - 17,  length = 15
  'Boris  Schäling'

group1 start/end  = 2 - 7,  length = 5
  'Boris'

group2 start/end  = 9 - 17,  length = 8
  'Schäling'
*/