fstream 的文件指针问题
文件以追加方式打开时,若文件已经存在,为什么tellp返回的仍然是0?
eg.
- C/C++ code
std::ofstream fs;fs.open("out.txt", std::ios::out|std::ios::app);fs << "hello world.";fs.close();fs.open("out.txt", std::ios::out|std::ios::app);// fs << "glad to see you."; // 毫无疑问这个写操作会写到hello world之后if( static_cast<size_t>(fs.tellp()) ){ cout << "out.txt already exists.\n";}fs.close();HP-UX 或 Win32+VS2008 环境下,上面的代码对文件写指针的测试都是失败的。
又测试了一下Win32 的 CreateFile 函数,用OPEN_ALWAYS打开文件,然后SetFilePointer获取文件指针,得到的文件指针位置也是0,这个倒可以理解,CreateFile不区分读写指针。
难道“tellp指向哪里下一次的写操作就写到哪里”这个规则不成立??那么tellp有什么意义呢?
求解.
[解决办法]
- C/C++ code
template<class _E, class _Tr> inline basic_ostream<_E, _Tr>& __cdecl operator<<( basic_ostream<_E, _Tr>& _O, const _E *_X) {typedef basic_ostream<_E, _Tr> _Myos; ios_base::iostate _St = ios_base::goodbit; size_t _N = _Tr::length(_X); size_t _M = _O.width() <= 0 || _O.width() <= _N ? 0 : _O.width() - _N; const _Myos::sentry _Ok(_O); if (!_Ok) _St |= ios_base::badbit; else {_TRY_IO_BEGIN if ((_O.flags() & ios_base::adjustfield) != ios_base::left) for (; 0 < _M; --_M) if (_Tr::eq_int_type(_Tr::eof(), _O.rdbuf()->sputc(_O.fill()))) {_St |= ios_base::badbit; break; } if (_St == ios_base::goodbit && _O.rdbuf()->sputn(_X, _N) != _N) _St |= ios_base::badbit; if (_St == ios_base::goodbit) for (; 0 < _M; --_M) if (_Tr::eq_int_type(_Tr::eof(), _O.rdbuf()->sputc(_O.fill()))) {_St |= ios_base::badbit; break; } _O.width(0); _CATCH_IO_(_O) } _O.setstate(_St); return (_O); }
[解决办法]
使用ios::app模式,新内容只会写到文件的后面,所以seekp、tellp没有起作用,但使用seekp后用tellp返回的位置是正确的。
在if( static_cast<size_t>(fs.tellp()) )前加上fs.seekp(0,ios::end);即可
要用tellp就别用app模式