我正在与ifstream一起玩,以熟悉它。我正在尝试使用seekg来告知文件的位置,但这给了我错误的结果。

这个想法是:

  • 打开文件
  • 文件的位置
  • 从文件
  • 读取字符
  • 文件的位置
  • 从文件
  • 读取字符
  • 文件的位置
  • 关闭文件。

  • 原始文件如下所示(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;
    }
    

    这分别是两个文本文件的两个十六进制编辑器 View :

    原始:c&#43;&#43; - ifstream::seekg给错误的结果-LMLPHP
    修改了:c&#43;&#43; - ifstream::seekg给错误的结果-LMLPHP

    我希望两者都能分别产生0、1、2的结果,但是原始实验并非如此。

    有人可以解释这里发生了什么吗?

    问题:
  • 我应该怎么做才能获得正确的文件位置?


  • 是什么导致f.tellg给这些奇怪的值0,6,7而不是默认的期望1,2,3?

  • 可能的解释(下面由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也有ios::binary,没有使用seek。总体而言,这两个问题具有不同的上下文,并且知道该问题的答案并不能回答该问题。

    最佳答案

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

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



    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()

    10-05 18:12