带有std :: ate的std :: ofstream最后没有打开

ine*_*ght 8 c++ fstream c++11

我正在尝试打开一个文件输出并附加到它.在附加到它之后,我想将输出位置移动到文件中的其他位置并覆盖现有数据.据我了解,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;
}
Run Code Online (Sandbox Code Playgroud)

特别地,似乎std::ios_base::ate没有初始输出指针移动到与上方看到的示例的端部.显然这会导致第一次写入覆盖文件的开头(这是导致我麻烦的原因).

似乎执行不正确或者cplusplus.com不正确("输出位置从文件末尾开始.")和cppreference.com不明确("在打开后立即寻找流的末尾":流?).

显然有一个简单的解决方法:只需使用stream.seekp(0, std::ios_base::end).

所以我的问题是:我的代码是不正确的?实施不正确吗?参考网站是否不正确?任何见解将不胜感激.

use*_*267 8

从N4296中的下图可以看出[filebuf.members]

文件io

该组合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会自动或std::ios_base::instd::ios_base::out分别与你提供的构造函数或任何标志open.您还可以使用对象本身来访问标志:

std::ofstream check("test", check.in | check.binary | check.ate);
Run Code Online (Sandbox Code Playgroud)

检查good也可缩短为if (!initial)等.

  • 哦,derp.*完全*有意义...当有特定的截断平面时,使用输入标志不截断.完全意义就在那里.这是问题所在.谢谢 :) (3认同)