Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

ofstreamでバイナリ追記モードで出力する時にハマった話

More than 1 year has passed since last update.

概要

ofstreamを使うとき、バイナリモードかつ末尾に追記の詳しい情報がなく、そもそも毎日はプログラミングしないので色々ど忘れしていて、見事にハマったのでメモ。
C/C++, ofstreamの初歩的な所に詰まった話なので、ベテランの方には価値のない情報です。
(※ 記事を書いた当初、初歩的なミスに気付いておらず、コメント頂いてから分かる始末。ご指摘ありがとうございました。)

コード見ればほぼ一発なので、サンプル内コメントを見てください。
ちなみに環境は Visual Studio 2017のVC++(C++)です。

main.cpp
#include <fstream>
using namespace std;

int main()
{
    ofstream ofs;
    string path = "./hoge.bin"; // パス区切り「/」「\\」は可、「\」は不可

    //// 暗黙の ios::trunc ?で開いた時に中身が消されちゃう
    // ofs.open(path.c_str(), ios::binary);

    //// ビット演算のORではなく、論理和のORになっている。
    //// 警告レベルを高めにしてもビルドエラーや警告は出ない。
    // ofs.open(path.c_str(), ios::app || ios::binary);

    ofs.open(path.c_str(), ios::app | ios::binary);
    if (!ofs) {
        return 1;
    }

    char dat[3] = { 0, 1, 2 };

    // これだけだと、close()するまで(? 少なくともこれくらいの字数では)ファイルに出力されない。
    ofs.write(dat, 3);

    // バッファの書き込み指令が出る。厳密にはこの命令で書き込むのではなく、遅延書き込みらしい?
    // ofs << flush; でも可。endl は、内部的に行われるので flush 不要。
    ofs.flush();

    ofs.close();
    return 0;
}


// 余談

//// これは機能しない。引数が streampos 型なので ios::end を使うのは間違い。
//// ビルドエラーや警告は出ない。
// ofs.seekp(ios::end)

// 第2引数は ofs.end でも可。
// (内部的にはどちらも、enum _Seekdir 内にある _Seekend が指定されているもよう。)
ofs.seekp(0, ios::end);

まとめ

コンパイラを過信しない。
思い込みはよくない。何かおかしいと思ったら、コーディングから疑うこと。

即時出力したい場合は flush する。

tatsubey
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away