ifstream :: seekg给出了错误的结果

时间:2017-05-31 17:54:30

标签: c++ ifstream seekg

我正在玩ifstream来熟悉它。我试图使用seekg来告诉文件的位置,但它给了我错误的结果。

这个想法是:

  1. 打开文件
  2. 打印文件的位置
  3. 从文件中读取一个字符
  4. 打印文件的位置
  5. 从文件中读取一个字符
  6. 打印文件的位置
  7. 关闭文件。
  8. 原始文件如下所示(Windows格式):

    file.txt的

    aA
    bB
    cC
    dD
    eE
    fF
    

    运行我的代码,我得到了结果:

    position: 0
    got: a
    position: 6
    got: A
    position: 7
    

    但是,对于这个文件:

    file.txt的

    aAbBcCdDeEfF
    

    我得到了这些结果

    position: 0
    got: a
    position: 1
    got: A
    position: 2
    

    以下是我使用的代码:

    TEST.CPP (适用的mingw / gcc5.3)

    #include <fstream>
    #include <iostream>
    
    using namespace std;
    
    static char s[10];
    
    int main(int argc, char **argv)
    {
        ifstream f("file.txt");    
        cout << "position: " << f.tellg() << "\n";
        f.read(s, 1);
        cout << "got: " << s << "\n";
        cout << "position: " << f.tellg() << "\n";
        f.read(s, 1);
        cout << "got: " << s << "\n";
        cout << "position: " << f.tellg() << "\n";    
        f.close();
    
        return 0;
    }
    

    以下是两个文本文件的两个十六进制编辑器视图:

    原创enter image description here 已修改enter image description here

    我希望两者分别得到结果0,1,2,但原始实验不是这样。

    有人能解释一下这里发生了什么吗?

    问题

    1. 我该怎么做才能获得正确的文件位置?
    2.   

      答案:在ifstream("file.txt", ios_base::in | ios_base::binary)构造函数上使用ifstream("file.txt")构造函数。

      1. 是什么导致f.tellg默认给出这些奇怪的值0,6,7而不是预期的1,2,3?
      2. 可能的解释(在下面测试Holt的答案)

        此代码中的

        f.tellg转向f.rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in),它负责生成值0,6,7(但仅在构造/打开时未指定ios_base::binary时)。

        #include <fstream>
        #include <iostream>
        
        using namespace std;
        
        static char s[10];
        
        int main(int argc, char **argv)
        {
            ifstream f("file.txt");    
            cout << "position: " << f.rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in) << "\n";
            f.read(s, 1);
            cout << "got: " << s << "\n";
            cout << "position: " << f.rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in) << "\n";
            f.read(s, 1);
            cout << "got: " << s << "\n";
            cout << "position: " << f.rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in) << "\n";
            f.close();
        
            return 0;
        }
        

        注意ios::in | ios::binary作为ifstream构造函数的第二个参数传递使两个文件的行为符合预期,但我也想知道是什么导致默认行为给出这些奇怪的tellg值

        注意tellg() function give wrong size of file?的区别。那个问题默认设置为ios :: binary,并使用seek;这个问题在这里有ios :: binary和without,并且不使用seek。总的来说,这两个问题有不同的背景,知道这个问题的答案并没有回答这个问题。

1 个答案:

答案 0 :(得分:5)

tellg()返回的值没有“错误”结果:当文件以文字模式打开时,返回值未指定(即它没有任何意义,除了它可以用作seekg())的输入。

基本上,tellg()上对basic_fstream的调用会回退到std::ftell 1 函数,该函数表示(C标准,§7.21.9.4[文件定位功能],重点是我的):

  

long int ftell(FILE *stream);

     

ftell函数获取stream指向的流的文件位置指示符的当前值。 [...]对于文本流,其文件位置指示符包含未指定的信息fseek函数可用于返回文件位置指示符   在ftell电话时流到其位置;两个这样的返回值之间的差异不一定是写入或读取的字符数的有意义的度量。

1 tellg()回退到rdbuf()->pubseekoff(0, std::ios_base::cur, std::ios_base::in),后退到basic_filebuf::seekoff(0, std::ios_base::cur, std::ios_base::in),然后回落到std::ftell()