ate模式下seekp()后tellp()返回-1问题排查及代码修正
关于C++中
seekp()和tellp()在ios::ate模式下的异常问题排查 最近在测试C++文件流的seekp()和tellp()函数时,碰到个让人困惑的问题:用ios::ate模式打开文件后,执行f2.seekp(10)再调用tellp(),返回值居然是-1。而且这个结果在Visual Studio和TDM GCC 4.9.2 64位编译器里完全一致,一开始我还以为是ate模式下seekp()有什么特殊限制,折腾了半天才发现是自己代码里的低级错误。
初始错误代码
/** 以ate模式打开,ios::in用于确保文件不被销毁 */ ofstream f2("h2.txt", ios::ate | ios::out | ios::in); if (!f2) //0表示错误,也可使用f1.fail() { // 打开失败 cerr << "cannot open the file\n"; exit(-1); } ios::pos_type currentPos = f2.tellp(); cout << "Initial Write Pointer Position = " << currentPos << endl; // 写入数据,应写入文件末尾 f2 << 20; currentPos = f2.tellp(); cout << "Write Pointer Position after write = " << currentPos << endl; // 定位到指定位置,文件指针应相应改变 f2.seekp(10); currentPos = f1.tellp(); // 此处存在错误,引用未定义的f1 cout << "Write Pointer Position after seek = " << currentPos << endl; // 写入数据 f2 << "ABC"; currentPos = f2.tellp(); cout << "Final Write Pointer seek and write = " << currentPos << endl; f2.close();
问题根源其实非常简单:调用tellp()时错误引用了未定义的f1,而非实际打开的文件流f2。f1从未被初始化过,调用它的成员函数自然会返回无效值-1,这跟seekp()本身的功能、ios::ate模式都没关系,纯粹是笔误导致的假异常。
修正后的完整代码
#include <iostream> #include <fstream> #include <string> using namespace std; int main() { string file_name; int currentPos; cout << "Enter the file name: "; getline(cin, file_name); fstream f2(file_name, ios::ate | ios::out | ios::in); if (!f2) // 0表示错误,也可使用f2.fail() { // 打开失败 cerr << "cannot open the file\n"; } else { currentPos = f2.tellp(); cout << "Initial Write Pointer Position = " << currentPos << endl; // 写入数据,应写入文件末尾 f2 << 20; currentPos = f2.tellp(); cout << "Write Pointer Position after write = " << currentPos << endl; // 定位到指定位置,文件指针应相应改变 f2.seekp(10); currentPos = f2.tellp(); cout << "Write Pointer Position after seek = " << currentPos << endl; // 写入数据 f2 << "ABC"; currentPos = f2.tellp(); cout << "Final Write Pointer seek and write = " << currentPos << endl; f2.close(); } return 0; }
修正的关键点:
- 将错误的
f1.tellp()改为f2.tellp(),引用正确的文件流对象 - 把错误提示里的
f1.fail()修正为f2.fail(),保持代码一致性 - 改用
fstream替代ofstream(虽然ofstream加ios::in也能运行,但fstream更贴合读写两用的场景) - 增加了必要的头文件,同时支持用户输入文件名,让代码更通用
修正后再次运行,seekp(10)可以正常将写指针定位到第10个位置,tellp()也会返回预期的正确数值——这说明ios::ate模式下seekp()的功能完全正常,之前的异常只是代码笔误造成的乌龙。
内容的提问来源于stack exchange,提问作者Rajesh
相关产品推荐
相关产品推荐

