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 直到 failed fputs()。之后,ferror(f)非零,但errno为0,所以我不知道问题出在哪里

我只在 Windows 上看到这一点,在 Visual Studio 2008 和 GCC 4.7.2 (MinGW) 中。在 Linux 上,相同的代码运行没有错误

4

1 回答 1

6

C 标准要求您在从“读取模式”切换到“写入模式”时进行搜索,反之亦然,除非在某些其他通常不值得列举的特殊情况之后。

一个实现(例如我多年前为 BSD 或 Linux 编写的那个)可能比要求的更宽容,使您的代码“正常工作”。(这真的很简单,您只需要在实现内部保留两个单独的计数器而不是单个组合计数器。)但是标准不要求实现是友好的,而 Windows 则不是。

于 2013-06-13T20:10:20.157 回答