std :: ofstream与std :: ate不打开结束 [英] std::ofstream with std::ate not opening at end

查看:312
本文介绍了std :: ofstream与std :: ate不打开结束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试打开一个文件进行输出并附加到它。添加后,我想将输出位置移动到文件中的其他位置,然后重写现有数据。据我所知, std :: ios_base :: app 强制 所有写入将在文件,这是不是我想做什么。因此,我相信 std :: ios_base :: ate 是传递到 std :: ofstream :: open()。但是,它似乎没有按预期工作:

I am trying to open a file for output and append to it. After appending to it, I want to move my output position somewhere else in the file and overwrite existing data. As I understand it, std::ios_base::app will force all writes to be at the end of the file which is not what I want to do. As such, I believe std::ios_base::ate is the correct flag to pass to std::ofstream::open(). However, it seems to be not working as expected:

// 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 不会将初始输出指针移动到上面所示示例的末尾。显然,这将导致第一次写覆盖文件的开头(这是什么导致我的麻烦)。

In particular, it seems that std::ios_base::ate does not move the initial output pointer to the end with the example seen above. Obviously this would result in the first write overwriting the beginning of the file (which is what caused my trouble).

似乎实现不正确,否则 cplusplus.com 不正确(输出位置从文件。)和 cppreference.com 不明确(

It seems that either the implementation is incorrect or else cplusplus.com is incorrect ("The output position starts at the end of the file.") and cppreference.com is ambiguous ("seek to the end of stream immediately after open": which stream?).

显然有一个简单的解决方法: code> stream.seekp(0,std :: ios_base :: end)。

There is obviously an easy workaround: just use stream.seekp(0, std::ios_base::end).

所以我的问题是:代码不正确?执行不正确吗?参考网站不正确吗?

So my question is thus: is my code incorrect? Is the implementation incorrect? Are the reference sites incorrect? Any insight would be appreciated.

推荐答案

从N4296 [filebuf.members]中的下列图表可以看到

As you can see from the following chart in N4296 [filebuf.members]

组合 binary | out 将打开 stdio 相当于wb code>截断为零长度或创建用于写入的二进制文件(N1570 7.21.5.2)。

The combination binary | out will open the file in the stdio equivalent of "wb", which will truncate to zero length or create binary file for writing (N1570 7.21.5.2).

ofstream ,如果您不想截断文件,则需要在 c>标志中添加 app 如果你想避免截断并在每次写入时寻找文件结尾。

As counterintuitive as it sounds for an ofstream, you will need to add the in flag if you don't want your file to be truncated, or app if you want to avoid truncation and seek to the end of the file on each write.

不像 fstream ifstream ofstream 会自动或 std :: ios_base :: in std :: ios_base :: out 分别与您提供给构造函数的任何标志或 open 。您还可以使用对象本身访问标志:

Bonus tip: Unlike fstream, ifstream and ofstream will automatically or std::ios_base::in and std::ios_base::out respectively with any flags you provide to the constructor or to open. You can also use the object itself to access the flags:

std::ofstream check("test", check.in | check.binary | check.ate);

good 的检查也可以缩短到 if(!initial)等。

The checks for good can also be shortened to if (!initial) etc.

这篇关于std :: ofstream与std :: ate不打开结束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆