代码之家  ›  专栏  ›  技术社区  ›  Evan Teran

fopen'd文件的默认输入和输出缓冲?

  •  7
  • Evan Teran  · 技术社区  · 14 年前

    因此,文件流可以同时具有输入和输出缓冲区。您可以使用 setvbuf (我不知道任何处理输入缓冲区大小和行为的方法)。

    此外,默认情况下,缓冲区是 BUFSIZ (不确定这是posix还是c的东西)。很清楚这意味着什么 stdin / stdout / stderr ,但新打开的文件的默认值是什么?它们是为输入和输出缓冲的吗?或者只是一个?

    如果是缓冲的,输出是否默认为块模式或行模式?

    编辑: 我做了一些测试,看看乔纳森·莱夫勒的回答是如何影响现实世界的节目的。如果你读了一本书,就好像写了一本书。写入操作将导致输入缓冲区中未使用的部分完全丢弃。事实上,会有一些寻求,以保持在正确的文件偏移量。我用了这个简单的测试程序:

    /* input file contains "ABCDEFGHIJKLMNOPQRSTUVWXYZ" */
    #include <stdio.h>
    #include <stdlib.h>
    
    int main() {
    
        FILE *f = fopen("test.txt", "r+b");
        char ch;
        fread(&ch, 1, 1, f);
        fwrite("test", 4, 1, f);
        fclose(f);
        return 0;
    }
    

    导致以下系统调用:

    read(3, "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", 4096) = 27 // attempt to read 4096 chars, got 27
    lseek(3, -26, SEEK_CUR)                 = 1        // at this point, I've done my write already, so forget the 26 chars I never asked for and seek to where I should be if we really just read one character...
    write(3, "test", 4)                     = 4        // and write my test
    close(3)                                = 0
    

    虽然这些显然是实现细节,但我发现它们对于如何实现标准库非常有趣。谢谢乔纳森给我的深刻回答。

    1 回复  |  直到 13 年前
        1
  •  6
  •   Jonathan Leffler vy32    14 年前

    单个文件流具有单个缓冲区。如果文件用于输入和输出,则必须确保在读写(或写读)操作之间执行适当的操作(fseek()或等效操作)。

    标准通道的缓冲行为取决于平台。

    通常,当输出到终端时,stdout是行缓冲的。但是,如果stdout要转到文件或管道而不是终端,它通常会切换到完全缓冲。

    通常,stderr是行缓冲或无缓冲的,以确保看到错误消息(例如,即使程序即将崩溃)。

    通常情况下,stdin是行缓冲的;这意味着您有机会编辑您的输入(错误上的退格等)。你很少会调整这个。同样,如果输入来自文件(或管道),则行为可能不同。

    新打开的文件通常会被完全缓冲。如果设备是终端,则特定实现可能会将其更改为行缓冲。

    你的假设——有两个缓冲区——是不正确的。


    C99第7.19.3节规定:

    在程序启动时,三个文本流是预定义的,不需要显式打开 标准输入(用于读取常规输入),标准输出(用于写入 常规输出)和标准错误(用于写入诊断输出)。开始时 打开时,标准错误流没有完全缓冲;标准输入和标准 当且仅当可以确定流不引用时,输出流被完全缓冲 到交互设备。

    所以,如前所述,stderr要么是无缓冲的 行缓冲(它没有完全缓冲)。