準備
まずは binary ファイルを用意
int main(void)
{
FILE *f = fopen("./in.dat", "wb");
char hoge[10] = "abcdefghi\0";
fwrite(hoge, sizeof(char), 10, f);
fclose(f);
}
binary モードで vim で開くと、
(vim -b in.dat
=> :%!xxd
)
00000000: 6162 6364 6566 6768 6900 abcdefghi.
本題
in.dat から読み込み、その内容を out.dat に出力する。
その後、out.dat を fread して、それを末尾に fwrite で追加しようとする。
そのとき、うまく書き込めない。
パターン1: 何も考えないで書く
# include <stdio.h>
int main(void)
{
char buff[10] = {0};
char buff2[10] = {0};
FILE *in = fopen("./in.dat", "rb");
FILE *out = fopen("./out.dat", "wb");
fread(buff, 1, 10, in);
fwrite(buff, 1, 10, out);
fseek(out, 0, SEEK_SET);
fread(buff2, 1, 10, out);
fseek(out, 10, SEEK_SET);
fwrite(buff2, 1, 10, out);
fclose(in);
fclose(out);
}
これをやると、うまくいかない
00000000: 6162 6364 6566 6768 6900 0000 0000 0000 abcdefghi.......
00000010: 0000 0000 ....
パターン2: fflush() する
バッファに残っているからでは?と思ったので fflush() してみる
# include <stdio.h>
int main(void)
{
char buff[10] = {0};
char buff2[10] = {0};
FILE *in = fopen("./in.dat", "rb");
FILE *out = fopen("./out.dat", "wb");
fread(buff, 1, 10, in);
fwrite(buff, 1, 10, out);
// ここで fflush
fflush(out);
fseek(out, 0, SEEK_SET);
fread(buff2, 1, 10, out);
fseek(out, 10, SEEK_SET);
fwrite(buff2, 1, 10, out);
fclose(in);
fclose(out);
}
これもうまくいかない
00000000: 6162 6364 6566 6768 6900 0000 0000 0000 abcdefghi.......
00000010: 0000 0000 ....
パターン3: setbuf() を使う
setbuf() を追加し、第二引数で NULL を指定することで、バッファリングをしないようにする。
(fflush でできているはずだが、念の為)
# include <stdio.h>
int main(void)
{
char buff[10] = {0};
char buff2[10] = {0};
FILE *in = fopen("./in.dat", "rb");
FILE *out = fopen("./out.dat", "wb");
// そもそもバッファリングしない
setbuf(out, NULL);
fread(buff, 1, 10, in);
fwrite(buff, 1, 10, out);
// ここで fflush
fflush(out);
fseek(out, 0, SEEK_SET);
fread(buff2, 1, 10, out);
fseek(out, 10, SEEK_SET);
fwrite(buff2, 1, 10, out);
fclose(in);
fclose(out);
これもうまくいかない
00000000: 6162 6364 6566 6768 6900 0000 0000 0000 abcdefghi.......
00000010: 0000 0000 ....
結論
よくわからないが fflush() とかしてもうまくいかないことがあるのだろうか。。。謎。。。
https://stackoverflow.com/questions/19062239/fclose-function-in-c-why-fread-works-but-not-fwrite-if-you-call-fclose-for
↑をみると、以下のようなコメントがある。
(Actually, I think there are some cases where data may not physically arrive
in the file even after fclose() or fflush().)
これは一体どういうケースなのだろうか・・・
追記
と思ったが、↓で解決した(コメントいただいた)。
FILE *out = fopen("./out.dat", "wb+");
fread するには +
をつけないといけないという初歩的なミス。。。
こういうときは fread が NULL を返すもんだと勘違いしていたのも気づけなかった原因だった。。