【问题标题】:How exactly does setvbuf fill the buffer?setvbuf 究竟是如何填充缓冲区的?
【发布时间】:2021-01-19 16:31:52
【问题描述】:

为了更好地理解setvbuf的用法,我有一些问题:

我想将文件中的一行读入缓冲区,然后随意读取/解析它。问题是,如何获得线路。我的印象是 _IOLBF 使 setvbuf 从流中逐行读取。从 C99 ISO 中,我了解到对 setvbuf 的调用只是为流分配了一个(或没有)缓冲区,但尚未对其进行操作。

所以我想,如果我之后从流中读取,它应该先填充缓冲区,然后从这个缓冲区执行操作(在这种情况下是读取)。那是对的吗?如果不是:它究竟是如何工作的?

这是一个小例子。我的期望是,一旦我调用 fread,缓冲区 buffer 将被字符填充,直到 \n 或达到给定的大小。然后我想用 printf 从缓冲区中取出行(或字符数)。 除了需要“正确”大小参数之外,它几乎按照我的解释方式工作。

#include <stdio.h>

#define BUF_SIZE 64

int main()
{
    char buffer[BUF_SIZE];
    char buffer2[BUF_SIZE];
    FILE* fp;
    fp = fopen("file.dat", "r");
    setvbuf(fp, buffer, _IOLBF, 64);
    fread(buffer2, 1, 32, fp);
    printf("buffer:\n%s\n", buffer);
    printf("buffer2:\n%s\n", buffer2);
    fclose(fp);
    return 0;
}

让我烦恼的是我读了

当流使用它进行缓冲时,您不应该尝试直接访问数组中的值。

如该链接所述:https://www.gnu.org/software/libc/manual/html_node/Controlling-Buffering.html

这是为什么呢?

最后我在这里读到: http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/016_c_ein_ausgabe_funktionen_020.htm (虽然这是德语,但我的问题中提供了理解这一点所需的一切。)

那句台词:

setvbuf(src, NULL, _IOLBF, 80);
setvbuf(dest, NULL, _IOLBF, 80);

将 80 个字符从 src 复制到 dest,我用我的文件流和 stdout 对其进行了测试,希望能在终端上看到输出。这没有用。为什么?

【问题讨论】:

  • setvbuf() 不读取任何内容。它分配文件流使用的空间。就这样。在将缓冲区交给流之后,您不应该戳它——它是供库使用的,而不是您。你不知道它用它做什么。行缓冲的流主要应用于输出——这意味着如果消息中有换行符,数据将被刷新。
  • setvbuf 不会(也不能)更改基于内容读取流的方式。它只是控制内部缓冲区和流之间发生 IO 时操作的时间和大小。如果将块大小设置为 80,则读取一次将读取 80 个字节。使流线缓冲意味着如果您 fwriteputc 换行,则流上将发生写入。
  • 另请注意,您应该在每个流中只使用一次setvbuf()。在对流进行任何 I/O 操作之前,您必须调用 setvbuf()
  • 访问缓冲区是explicitly undefined behavior:“尝试使用在调用setvbuf 函数时提供的数组内容”
  • POSIX 有一个 getline 函数,可以从 stdio 流中读取整行。如果一个实现的 C 运行时库没有getline,那么编写一个等价的函数并不是困难的。

标签: c io buffer


【解决方案1】:

您不能以任何有用的方式真正依赖它。规范以模糊、笼统的方式描述了不同的缓冲模式,因为不同的环境和流类型对执行 I/O 的方式有限制。

在规范的Files 部分它说:

当流没有缓冲时,字符会尽快从源或目标出现。否则,字符可能会作为一个块累积并传输到主机环境或从主机环境传输。当一个流被完全缓冲时,当缓冲区填满时,字符将作为一个块传输到主机环境或从主机环境传输。当流被行缓冲时,当遇到换行符时,字符将作为块传输到主机环境或从主机环境传输。此外,当缓冲区被填满时,当在非缓冲流上请求输入时,或者当在需要从主机环境传输字符的行缓冲流上请求输入时,字符将作为块传输到主机环境. 对这些特性的支持是实现定义的,并且可能会受到 setbuf 和 setvbuf 函数的影响。

setvbuf 本身的描述中说:

参数模式决定如何缓冲流,如下所示: _IOFBF 导致输入/输出被完全缓冲; _IOLBF 导致输入/输出被行缓冲; _IONBF 导致输入/输出无缓冲。如果 buf 不是空指针,则可以使用它指向的数组而不是 setvbuf 函数分配的缓冲区273) 并且参数 size 指定数组的大小;否则,size 可能决定由 setvbuf 函数分配的缓冲区的大小。 数组的内容在任何时候都是不确定的。

【讨论】:

    猜你喜欢
    • 2020-02-14
    • 1970-01-01
    • 2015-10-18
    • 2019-07-19
    • 2021-12-22
    • 2017-01-05
    • 2021-12-26
    • 2011-02-20
    • 2017-10-10
    相关资源
    最近更新 更多