0
0

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-11-06

概要

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 する。

0
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0