我正在尝试打开一个输出文件并将其附加到其中。附加后,我希望将输出位置移到文件中的其他位置,并覆盖现有数据。据我所知,std::ios_base::app将强制将全部写在文件的末尾,这不是我想要做的。因此,我认为std::ios_base::ate是传递给std::ofstream::open()的正确标志。然而,它似乎没有象预期的那样发挥作用:
// g++ test.cpp
// clang++ test.cpp
// with and without -std=c++11
#include <iostream>
#include <fstream>
int main() {
std::streampos fin, at;
{
std::ofstream initial;
initial.open("test", std::ios_base::out | std::ios_base::binary);
if ( not initial.good() ) {
std::cerr << "initial bad open" << std::endl;
return 1;
}
int b = 100;
initial.write((char*)&b, sizeof(b));
initial.flush();
if ( not initial.good() ) {
std::cerr << "initial write bad" << std::endl;
return 1;
}
fin = initial.tellp();
}
{
std::ofstream check;
check.open("test", std::ios_base::out | std::ios_base::binary | std::ios_base::ate);
if ( not check.good() ) {
std::cerr << "check bad open" << std::endl;
return 1;
}
at = check.tellp();
if ( fin != at ) {
std::cerr << "opened at wrong position!\nfin:\t" << fin << "\n" << "at:\t" << at << std::endl;
return 1;
}
int bb = 200;
check.write((char*)&bb, sizeof(bb));
check.flush();
if ( not check.good() ) {
std::cerr << "check write bad" << std::endl;
return 1;
}
at = check.tellp();
}
if ( (fin + std::streampos(sizeof(int))) != at ) {
std::cerr << "overwrite?\nfin:\t" << fin << "\n" << "at:\t" << at << std::endl;
return 1;
}
return 0;
}特别是,在上面的示例中,std::ios_base::ate似乎没有将初始输出指针移到末尾。显然,这将导致第一次写入覆盖文件的开头(这就是我的麻烦所在)。
似乎要么实现不正确,要么cplusplus.com不正确(“输出位置从文件末尾开始”)。cppreference.com是模棱两可的(“在打开后立即查找到流的末尾”:哪个流?)。
显然有一个简单的解决方法:只需使用stream.seekp(0, std::ios_base::end)。
因此,我的问题是:我的代码不正确吗?实施是否不正确?参考站点是否不正确?任何洞察力都将不胜感激。
发布于 2015-03-12 00:27:04
如N4296 filebuf.members中的下图所示

组合binary | out将以stdio等效的"wb"打开文件,后者将是truncate to zero length or create binary file for writing (N1570 7.21.5.2)。
对于一个ofstream来说,这听起来是违反直觉的,如果您不希望您的文件被截断,则需要添加in标志,如果您希望避免截断并在每次写入时寻求文件的末尾,则需要添加app。
额外提示:与fstream不同的是,ifstream和ofstream将自动或分别使用向构造函数或open提供的任何标志的std::ios_base::in和std::ios_base::out。还可以使用对象本身访问标志:
std::ofstream check("test", check.in | check.binary | check.ate);对good的检查也可以缩短为if (!initial)等。
https://stackoverflow.com/questions/28999745
复制相似问题