首页 文章

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

提问于
浏览
1

我正在玩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;
}

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

original
enter image description here
modified
enter image description here

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

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

Questions

  • 如何获得正确的文件位置?

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

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

possible explanation (测试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;
}

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

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

1 回答

  • 5

    tellg() 返回的值没有"wrong"结果:当文件在 text mode 中打开时,返回值为 unspecified (即它没有任何意义,除了它可以用作 seekg() 的输入) .

    基本上,对 basic_fstreamtellg() 的调用回退到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() .

相关问题