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