使用seekg定位文件指针后无法读取完整行的问题求助
问题描述
尝试使用seekg移动到记录的文件指针位置后读取.txt文件的一行,尽管指针位置数值相同,但读取结果不完整。编译环境为x86架构Windows 11系统下的MinGW 11.2.0 64位编译器。
test.txt内容
2 33.10 30.10 29.90 33.00 33.20 33.00 32.90 33.10 40.20 40.20 40.00 39.90 40.30 37.20 40.30 36.70 4 33.00 30.10 29.90 33.00 33.10 32.90 32.90 33.00 40.30 40.20 40.00 40.00 40.30 37.30 40.20 36.70 6 33.00 30.10 29.90 33.00 33.10 33.00 32.90 33.00 40.20 40.30 40.10 40.00 40.20 37.20 40.10 36.90
测试代码
#include <iostream> #include <fstream> #include <string> using namespace std; int main(){ string file_path = "./test.txt"; string s; // don't use seekg fstream f(file_path); getline(f, s); int p = f.tellg(); cout << "the cur pos is:" << p << endl; getline(f, s); cout << s << endl; getline(f, s); cout << s << endl; f.close(); // use seekg fstream t(file_path); t.seekg(p, ios::beg); p = t.tellg(); cout << "the cur pos is:" << p << endl; getline(t, s); cout << s << endl; }
程序输出
the cur pos is:139 2 33.10 30.10 29.90 33.00 33.20 33.00 32.90 33.10 40.20 40.20 40.00 39.90 40.30 37.20 40.30 36.70 4 33.00 30.10 29.90 33.00 33.10 32.90 32.90 33.00 40.30 40.20 40.00 40.00 40.30 37.30 40.20 36.70 the cur pos is:139 2.90 33.10 40.20 40.20 40.00 39.90 40.30 37.20 40.30 36.70
补充说明(内存中字符串s)
2\t33.10\t30.10\t29.90\t33.00\t33.20\t33.00\t32.90\t33.10\t40.20\t40.20\t40.00\t39.90\t40.30\t37.20\t40.30\t36.70 4\t33.00\t30.10\t29.90\t33.00\t33.10\t32.90\t32.90\t33.00\t40.30\t40.20\t40.00\t40.00\t40.30\t37.30\t40.20\t36.70 2.90\t33.10\t40.20\t40.20\t40.00\t39.90\t40.30\t37.20\t40.30\t36.70
问题分析
核心原因是Windows下文本模式与二进制模式的换行符处理差异:
- 默认以文本模式打开文件时,Windows系统会将文件中的
\r\n(两个字节)自动转换为\n(一个字节)处理。 tellg()返回的是文本模式下的逻辑位置,而非文件实际的字节偏移量。- 重新打开文件后用
seekg()跳转到之前记录的逻辑位置时,由于新的文本模式转换,该位置对应的实际文件字节位置与预期不符,导致读取到行的中间部分。
解决方案
将文件以二进制模式打开,这样tellg()和seekg()操作的是文件实际的字节偏移,不会有换行符的转换问题。修改代码中打开文件的部分,添加ios::binary标志:
修改后的完整代码:
#include <iostream> #include <fstream> #include <string> using namespace std; int main(){ string file_path = "./test.txt"; string s; // don't use seekg fstream f(file_path, ios::in | ios::binary); getline(f, s); int p = f.tellg(); cout << "the cur pos is:" << p << endl; getline(f, s); cout << s << endl; getline(f, s); cout << s << endl; f.close(); // use seekg fstream t(file_path, ios::in | ios::binary); t.seekg(p, ios::beg); p = t.tellg(); cout << "the cur pos is:" << p << endl; getline(t, s); cout << s << endl; }
这样修改后,tellg()记录的是实际字节偏移,seekg()跳转后能准确指向第二行的起始位置,读取到完整的行内容。
内容的提问来源于stack exchange,提问作者Malloc
相关产品推荐
相关产品推荐

