[英]Setting file pointer position
作為示例,請考慮以下文件的示例:
Associative 19 78 45 23
Disjunctive 23 45 02 200
Associative 23 546 32 56
Conjunctive 22 22 00 3478
Disjunctive 11 934 88 34
我的目標 :
為所有“Associatives”,“Disjunctives”和“Conjunctives”做一系列操作。 該文件非常大,未進行排序。 我可以使用bash進行額外的排序操作,但只考慮我想避免它的情況。
我的方法 :
Step 1 : Open the file using **std::ifstream**
Step 2 : Create an unordered set to store the unique first words.
Step 3 : Create a multimap of type multimap<std::string,streampos>
Step 4 : Traverse the file using std::ifstream::ignore, and keep adding the first word to the unordered set, and stream position to the multimap alongwith the first word.
Step 5 : The thought is that in this way a primary index of stream position and line numbers is being created.
Step 6 : Now go through each element of the unordered set and use multimap::equal_range to look for stream positions for that key.
Step 7 : Traverse through those stream positions and do your operation
Q1。 這種方法是否正確使用C ++從文件中讀取特定行?
Q2。 以下是我編寫的用於測試此想法的C ++程序的基本片段。 但是我沒有找到成功的想法。 該計划已經完成。 您只需復制並粘貼代碼,然后使用上面的文本文件樣本即可查看輸出。 具體問題如下:當我使用seekg設置流位置然后嘗試讀取一行時,似乎沒有任何反應(即流位置沒有改變)。 代碼段如下:
#include<iostream>
#include<fstream>
#include<limits>
#include<unordered_set>
#include<map>
using namespace std;
int main(int argc,char* argv[])
{
if (argc<2)
{
cout<<"Usage: get_negatives <Full Path of Annotation File> \n"<<endl;
return 0;
}
ifstream fileGT;
fileGT.open(argv[1]);//Open the file containing groundtruth annotations
string filename;
unordered_set<string> unique_files; //Open this unordered set to uniquely store the file names
multimap<string,streampos> file_lines; //Open this multimap to store the file names as keys and corresponding line numbers as the values
streampos filepos = fileGT.tellg();
fileGT>>filename;
unique_files.insert(filename);
file_lines.insert(pair<string,streampos>(filename,filepos));
while(!fileGT.eof())
{
fileGT.ignore(numeric_limits<streamsize>::max(),'\n');
filepos = fileGT.tellg();
fileGT>>filename;
unique_files.insert(filename);
file_lines.insert(pair<string,streampos >(filename,filepos));
}
for(auto it=unique_files.begin(); it!=unique_files.end(); ++it)
{
pair<multimap<string,streampos>::iterator, multimap<string,streampos>::iterator>range_vals;
range_vals = file_lines.equal_range(*it);
for(auto it2=range_vals.first; it2!=range_vals.second; ++it2)
{
fileGT.seekg(it2->second,ios_base::beg);
getline(fileGT,filename);
cout<<filename<<endl;
}
}
return -1;
}
問題是如果設置了一些錯誤位, seekg()
有時會無法正常工作。
你必須始終調用fileGT.clear()
每前fileGT.seekg()
我認為這應該是C ++ 11中的默認模式,但我不打算這樣做。
此外,每次閱讀后檢查錯誤是個好主意:
if (!getline(fileGT, filename))
//error handling
而且,正如我在評論中所說,如果你要去尋找,你必須用std::ios::binary
打開文件。
我沒有測試過您的代碼,但我建議您進行一些更改:
我遇到的大多數操作系統都使用約定,對於main的返回值,對於典型/正確的輸出return 0
,對於異常情況return 1
(或非零)。
除非你真的需要,否則不要使用\\n
和endl
,我不認為這是一個案例。
考慮重新排序while
循環,以便ignore
最后,請考慮以下事項:
。
std::string buf;
std::ifstream fp("input");
while (fp)
{
if (fp >> buf) { /* do something with buf */ }
fp.ignore(streamsize::max(), '\n');
}
無論何時從流中讀取,都不要假設輸出正常或流仍然有效。 檢查錯誤標志(使用bool重載或fp.good()
)。 只檢查fp.eof()
可能並不總是足夠的。
如果您正在使用C ++ 11,即使在到達文件末尾之后, seekg
應運行正常,但在早期版本中,您需要使用fp.clear()
清除流錯誤位。
如果您沒有使用C ++ 11進行編譯,則auto
關鍵字可能無法執行您認為的操作,請注意。 您可能還想考慮const auto&
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.