【发布时间】:2017-05-31 17:54:29
【问题描述】:
我正在使用 ifstream 来熟悉它。我正在尝试使用 seekg 来判断文件的位置,但它给了我错误的结果。
这个想法是:
- 打开文件
- 文件的打印位置
- 从文件中读取一个字符
- 文件的打印位置
- 从文件中读取一个字符
- 文件的打印位置
- 关闭文件。
原始文件是这样的(windows格式):
文件.txt
aA
bB
cC
dD
eE
fF
运行我的代码,我得到了结果:
position: 0
got: a
position: 6
got: A
position: 7
但是,对于这个文件:
文件.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;
}
这里分别是两个文本文件的两个十六进制编辑器视图:
我预计两者都会分别产生结果 0、1、2,但原始实验并非如此。
有人能解释一下这里发生了什么吗?
问题:
- 我应该怎么做才能获得正确的文件位置?
答案:使用
ifstream("file.txt", ios_base::in | ios_base::binary)构造函数而不是ifstream("file.txt")构造函数。
- 是什么原因导致 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 和没有,并且不使用 seek。总的来说,这两个问题有不同的上下文,知道该问题的答案并不能回答这个问题。
【问题讨论】:
-
在十六进制编辑器中比较文件。也许在文件的开头有一个 BOM 或一些奇怪的看不见的废话,操作系统会为您读取并跳过(除非您以二进制模式打开文件)。
-
在底部添加了十六进制视图。前 2 个字符是相同的,所以我看不出它会如何影响 seekg。
-
您使用的是什么操作系统和编译器?请提供确切的版本。
-
@Dmitry 当文件以文本模式打开时,
tellg()的返回值是未指定的(它只是用作seekg()的参数)。