簡體   English   中英

設置文件指針位置

[英]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 (或非零)。

  • 除非你真的需要,否則不要使用\\nendl ,我不認為這是一個案例。

  • 考慮重新排序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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM