3

这段代码只为行缓冲分配了 10 个字节,并读取了一个第一行有 45 个字节的文件。当它运行时,程序会读取所有 45 个字节,而不仅仅是我预期的前 10 个字节,那么setvbuf实际上做了什么?

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *tst;
    tst = fopen("x.log","r");

    char *buff = malloc(10); //Just 10 characters
    setvbuf(tst, buff, _IOLBF, 10);

    char *mystring = malloc(45); //First line of x.log is 45 characters exactly
    if ( fgets (mystring, 45, tst) != NULL )
        puts(mystring);
    fclose (tst);
    free(buff);
}
4

4 回答 4

3

fgets()在内部使用getc(),一次读取一个字符,直到它读取换行符或达到给定的限制。每当getc()到达 I/O 缓冲区的末尾时,它都会重新填充缓冲区,因此它不受setvbuf(). 设置较小的缓冲区大小只会降低效率,但不会改变可以读取的数据量。

于 2013-10-26T10:37:17.813 回答
1

setvbuf 将大小为 10 的缓冲区与文件相关联。

为什么要读取所有 45 个字节?

您正在使用 fgets 读取文件,并尝试读取 45 个字节。由于文件缓冲区大小为 10(和 _IOLBF 选项),这意味着读取是通过以下方式完成的:

  1. 从文件读取字节 0-9 到 mystring
  2. 读取字节 10-19...
  3. 读取字节 20-29...
  4. 读取字节 30-39...
  5. 读取字节 40-45 并在 \n 处停止

而不是使用默认缓冲区并可能一次读取所有字节(无需重新填充缓冲区)

于 2013-10-26T10:41:09.533 回答
1
setvbuf(tst, buff, _IOLBF, csize * 10);

您将缓冲模式设置为 _IOLBF = Line Buffered,根据 setvbuf 的手册页“...当它是行缓冲字符时,将保存到换行符...”

setvbuf(tst, buff, _IOFBF, csize * 10);

应该只缓冲 10 个字节,但 fgets 仍会读取整行。

缓冲意味着,内部数据被读取到缓冲区,当缓冲区已满或在行缓冲时,当读取换行符时,缓冲区被覆盖。

于 2013-10-26T10:41:25.320 回答
1

没有和有的区别setvbuf是,

open("file.txt", O_RDONLY)              = 3
read(3, "Hickanckdnckncksckscskcnnacnckad"..., 4096) = 65

Vs

open("file.txt", O_RDONLY)              = 3
read(3, "Hickanckdn", 10)               = 10
read(3, "cknckscksc", 10)               = 10
read(3, "skcnnacnck", 10)               = 10
read(3, "adjsnccnad", 10)               = 10 
read(3, "ncacsjcadj", 10)               = 10

fgets()一次读取4096大量字节。setvbuf是控制的方式,而缓冲区有多大read

于 2013-10-26T10:47:24.650 回答