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

Dmi*_*try 1 c++ ifstream seekg

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

这个想法是:

  1. 打开文件
  2. 打印文件的位置
  3. 从文件中读取一个字符
  4. 打印文件的位置
  5. 从文件中读取一个字符
  6. 打印文件的位置
  7. 关闭文件.

原始文件看起来像这样(Windows格式):

file.txt的

aA
bB
cC
dD
eE
fF
Run Code Online (Sandbox Code Playgroud)

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

position: 0
got: a
position: 6
got: A
position: 7
Run Code Online (Sandbox Code Playgroud)

但是,对于此文件:

file.txt的

aAbBcCdDeEfF
Run Code Online (Sandbox Code Playgroud)

我得到了这些结果

position: 0
got: a
position: 1
got: A
position: 2
Run Code Online (Sandbox Code Playgroud)

这是我使用的代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

原件:在此输入图像描述 修改:在此输入图像描述

我希望两者分别得到结果0,1,2,但原始实验并非如此.

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

问题:

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

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

  1. 是什么导致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;
}
Run Code Online (Sandbox Code Playgroud)

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

注意tellg()函数的区别是文件大小错误吗?.那个问题默认设置为ios :: binary,并使用seek; 这个问题在这里有ios :: binary和without,并且不使用seek.总的来说,这两个问题有不同的背景,知道这个问题的答案并没有回答这个问题.

Hol*_*olt 5

对于返回的值,没有任何"错误"结果tellg():当在文本模式下打开文件时,返回值未指定(即除了可以用作输入之外没有任何意义seekg()).

基本上,到呼叫tellg()上的basic_fstream回落到1个功能,它说(C标准,§7.21.9.4[文件定位功能],强调的是矿):std::ftell

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