LoginSignup
1
0

More than 5 years have passed since last update.

fwrite 直後に fread しても読み込めないことがある(と思ったらそんなことはなかった)

Last updated at Posted at 2018-07-18

準備

まずは 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 を返すもんだと勘違いしていたのも気づけなかった原因だった。。

1
0
4

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
1
0