4

Windows でファイルの書き込みに失敗するという問題が発生しています。この例に単純化しました。

FILE* f = fopen("test.out", "r+b");
fseek(f, -1, SEEK_END); // one byte before the end
printf("read byte: %c\n", fgetc(f)); // read the last byte; now at the end
printf("attempting write: %d\n", fputs("text", f));

これは の最後のバイトを正しく出力しますtest.outが、 はfputs失敗して -1 を返します。これらの同様の例はすべて正常に機能します。

  • 読まない

    FILE* f = fopen("test.out", "r+b");
    fseek(f, 0, SEEK_END); // this is where I ended up after the fgetc() above
    printf("attempting write: %d\n", fputs("text", f));
    
  • 読んだら最後までシークする (既にそこにいるにもかかわらず)

    FILE* f = fopen("test.out", "r+b");
    fseek(f, -1, SEEK_END);
    printf("read byte: %c\n", fgetc(f));
    fseek(f, 0, SEEK_END);
    printf("attempting write: %d\n", fputs("text", f));
    
  • 私たちがすでにいる場所を正確に求めてください

    FILE* f = fopen("test.out", "r+b");
    fseek(f, -1, SEEK_END);
    printf("read byte: %c\n", fgetc(f));
    fseek(f, ftell(f), SEEK_SET);
    printf("attempting write: %d\n", fputs("text", f));
    
  • 読み取りますが、最後のバイトではありません

    FILE* f = fopen("test.out", "r+b");
    fseek(f, -2, SEEK_END); // two bytes before the end
    printf("read byte: %c\n", fgetc(f)); // read the penultimate byte
    printf("attempting write: %d\n", fputs("text", f));
    
  • 最後まで読んで(...)

    FILE* f = fopen("test.out", "r+b");
    fseek(f, -1, SEEK_END); // one byte before the end
    printf("read byte: %c\n", fgetc(f)); // read the last byte; now at the end
    printf("read byte: %c\n", fgetc(f)); // read a garbage byte
    printf("attempting write: %d\n", fputs("text", f));
    

これらはすべてストリーム エラーまたは eof の問題を示しているように見えますがferror(f)feof(f)どちらも失敗するまで 0 を返しますfputs()。After,ferror(f)は非ゼロですが、errno0 であるため、何が問題なのかわかりません

これは Windows でのみ、Visual Studio 2008 と GCC 4.7.2 (MinGW) の両方で見られます。Linux では、同じコードがエラーなしで実行されます

4

1 に答える 1

6

C 標準では、「読み取りモード」から「書き込みモード」に、またはその逆に切り替えるときにシークを行う必要があります。

実装 (私が何年も前に BSD 用に書いたものや Linux のものなど) は、必要以上に寛容であり、コードを「正常に機能させる」ことができます。(これは非常に簡単です。実装内で、1 つの結合されたカウンターではなく、2 つの別個のカウンターを保持する必要があるだけです。) しかし、標準では、実装がフレンドリーである必要はなく、Windows のものはそうではありません。

于 2013-06-13T20:10:20.157 に答える