2013-03-06 88 views
0

我有一個可變長度的日誌文件,它可能包含或不包含我正在查找的字符串。從文本文件中提取某些行的最有效方法

行有時間戳等,然後<參數>#<值>我想檢查參數並提取值。

下面的實現工作,但我相信必須有一個更有效的方法來解析文件。

要點:

  • 大部分線路都將被忽略
  • 有大約1 16個時至日誌文件 - MB 甚至每個文件一個小的收穫將是一個優勢

NB。解析函數調用的子字符串然後將其轉換是爲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(); 
+1

您是否運行了一個分析器來查看您的代碼花費的最多時間?這通常是幫助優化的好主意。 – Floris 2013-03-06 17:10:26

+0

@dougie:畢竟你成功地使你的搜索效率? – 2015-02-01 17:25:07

回答

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; 
    } 
} 

當然,您需要相應地修改正則表達式。

不幸的是,iostreams已知很慢。如果你得不到足夠的性能,你可能會考慮用FILE *或mmap替換fstream。

+0

正則表達式似乎加快了一點。我使用了一次讀取大文件,然後創建一個只包含我感興趣的值的較小文件,並將其重命名爲原始(大)文件名。這種方法意味着第一次運行速度較慢,但​​未來運行時間很短。 @Slava冗餘線可能不需要,但他們不是很好的做法? – dougie 2013-03-08 09:31:19

+0

@dougie這不是一個簡單的問題。代碼應該是可讀的。從這個角度來看,IMO close()調用很好,儘管多餘。但是,如果語句不添加任何內容,只會使代碼更不可讀。 – Slava 2013-03-08 13:52:09

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

對於完全定製你總是可以使用精神。 http://www.boost.org/doc/libs/1_53_0/libs/spirit/doc/html/index.html

+0

可悲的是我不能使用boost庫,但會看看靈感鏈接 – dougie 2013-03-06 17:29:50

+0

爲什麼你不能使用boost庫?然而,這裏的另一個答案暗示。如果您可以使用C++ 11,則支持標準庫中的正則表達式。 – AxelOmega 2013-03-06 17:32:56

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++

0

您的執行瓶頸將出現在文件I/O中。
我建議你在一個緩衝區中抓取儘可能多的數據。接下來,搜索您的令牌的緩衝區。

你必須閱讀文本才能搜索它,所以你最好儘可能多的閱讀文件。

將太多數據讀入內存可能會有一些缺點。如果操作系統不適合所有的數據,它可能會將其分頁到硬盤,這使得該技術變得毫無價值(除非您希望操作系統處理以塊爲單位讀取文件)。

一旦文件在內存中,搜索技術可能會忽略不計的性能提升。

相關問題