【问题标题】:Why do I need to flush my I/O stream to get the correct result?为什么我需要刷新 I/O 流才能获得正确的结果?
【发布时间】:2011-01-14 21:30:51
【问题描述】:

为什么下面的代码不起作用?我的意思是,它在控制台输出上显示了各种奇怪的字符。

#include <stdio.h>
char mybuffer[80];
int main()
{
    FILE * pFile;
    pFile = fopen ("example.txt","r+");
    if (pFile == NULL) perror ("Error opening file");

    else {
        fputs ("test",pFile);

        fgets (mybuffer,80,pFile);
        puts (mybuffer);
        fclose (pFile);
        return 0;
    }
}

但是,下面的代码运行良好。

#include <stdio.h>
char mybuffer[80];
int main()
{
    FILE * pFile;
    pFile = fopen ("example.txt","r+");
    if (pFile == NULL) perror ("Error opening file");

    else {
        fputs ("test",pFile);
        fflush (pFile);    
        fgets (mybuffer,80,pFile);
        puts (mybuffer);
        fclose (pFile);
        return 0;
    }
}

为什么我需要刷新流以获得正确的结果?

【问题讨论】:

    标签: c iostream


    【解决方案1】:

    因为标准是这样说的(§7.19.5.3/5):

    当文件以更新模式打开时 ('+' 作为第二个或第三个字符 在上面的模式参数列表中 值),输入和输出都可以是 在关联的流上执行。 但是,输出不得直接 后跟输入没有 干预对 fflush 的调用 函数或文件定位 函数(fseek、fsetpos 或 rewind), 并且输入不得直接 其次是没有输出 干预对文件定位的调用 函数,除非输入操作 遇到文件结尾。

    这是有原因的:输出和输入通常是分开缓冲的。当有刷新或查找时,它会将缓冲区与文件同步,否则会使它们不同步。这通常会提高性能(例如,当您进行读取时,它不必检查您正在读取的位置是否在数据被读入缓冲区后已被写入)。

    【讨论】:

    • @Lee:很简单,你从停止写作的地方开始阅读它,你需要回到开头才能让它起作用。
    • @Lee:因为你写的“测试”还没有被读入读缓冲区。一种可能的情况是,当您打开文件时,它会尝试填充读取缓冲区。由于文件是空的,它设置一个标志来表示没有可用的输入。在您执行刷新或搜索之前,它将一直以这种方式标记,因此所有读取尝试都将失败。
    【解决方案2】:

    当使用具有读/写模式的文件时,您必须在不同的 i/o 操作之前调用 fseek/fflush。

    why fseek or fflush is always required...查看这个答案

    【讨论】:

    • 谢谢;我应该更努力地搜索
    【解决方案3】:

    因为 C 文件 io 使用缓冲区工作。只有在刷新它、写入 /n 字符或填满缓冲区时才会将其写入磁盘。

    所以在第一种情况下,当您读取文件时,您的文件不包含任何内容。

    【讨论】:

    • 但是即使我使用“test\n”而不是“test”,它仍然不起作用。
    • 这方面的答案是错误的:将\n写入文件完全没有效果;您必须刷新文件或写入太多数据,C 库将自行刷新(通常为 4KiB)。
    • 我认为 \n 位取决于实现 - MS 确实如此,至少对于 C++ 代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多