全缓冲流在未满时被刷新
fully-buffered stream get flushed when it is not full
我真的很困惑缓冲区的工作原理。所以我写了一个小片段来验证:
#include<stdio.h>
#define BUF_SIZE 1024
char buf[BUF_SIZE];
char arr[20];
int main()
{
FILE* fs=fopen("test.txt","r");
setvbuf(fs,buf,_IOFBF,1024);
fread(arr,1,1,fs);
printf("%s",arr);
getchar();
return 0;
}
如您所见,我将文件流 fs
设置为 fully buffered
流(我知道大多数情况下它会默认为完全缓冲。只需确保)。而且我还将它的相关缓冲区设置为大小 1024
,这意味着流不会被刷新,直到它包含 1024 字节的东西(对吗?)。
在我看来,fread()
的套路是,从文件流中读取数据,存入其缓冲区buf
,然后buf
中的数据一旦充满了 1024 字节的数据,就会被发送到 arr
(对吧?)。
但是现在,我只从流中读取了一个字符!!而且,文件中只有四个字符test.txt
。为什么我可以在 arr
中找到一些东西,如果只有一个字符(我可以打印出那个字符)
据我了解,输入缓冲区的工作方式与您建议的不同:如果您请求读取一个字节,系统会向缓冲区中读取另外 1023 个字节,因此在接下来的 1023 个后续读取调用中,它可以 return 直接从缓冲区中获取数据,而不必从文件中读取。
全缓冲、行缓冲和无缓冲之间的区别实际上只对输出流有影响。我很确定输入流几乎总是像完全缓冲一样。
但即使对于完全缓冲的输入流,也至少有一种情况是缓冲区不会完全满,正如您所发现的那样,输入中没有足够的字符来填充缓冲区。如果文件中只有4个字符,那么当系统去填充缓冲区时,它会得到这4个字符并将它们放入缓冲区,然后你就可以像往常一样开始取出它们了。
(只要文件包含的字符数不是缓冲区大小的精确倍数,就会出现同样的情况。例如,如果输入文件包含 1028 个字符,那么在用前 1024 个字符填充缓冲区后字符并让您读取它们,下次它填充缓冲区时,它会再次以 4 结束。)
在这种情况下,您期望它做什么?阻止等待从文件中再读取 1,020 个字符(这些字符永远不会出现)?
P.S。你说 "the stream would not be flushed until it contained 1024 bytes of stuff, right?" 但是 flushing 只是为 output 流定义的;它对输入流没有任何意义。
我真的很困惑缓冲区的工作原理。所以我写了一个小片段来验证:
#include<stdio.h>
#define BUF_SIZE 1024
char buf[BUF_SIZE];
char arr[20];
int main()
{
FILE* fs=fopen("test.txt","r");
setvbuf(fs,buf,_IOFBF,1024);
fread(arr,1,1,fs);
printf("%s",arr);
getchar();
return 0;
}
如您所见,我将文件流 fs
设置为 fully buffered
流(我知道大多数情况下它会默认为完全缓冲。只需确保)。而且我还将它的相关缓冲区设置为大小 1024
,这意味着流不会被刷新,直到它包含 1024 字节的东西(对吗?)。
在我看来,fread()
的套路是,从文件流中读取数据,存入其缓冲区buf
,然后buf
中的数据一旦充满了 1024 字节的数据,就会被发送到 arr
(对吧?)。
但是现在,我只从流中读取了一个字符!!而且,文件中只有四个字符test.txt
。为什么我可以在 arr
中找到一些东西,如果只有一个字符(我可以打印出那个字符)
据我了解,输入缓冲区的工作方式与您建议的不同:如果您请求读取一个字节,系统会向缓冲区中读取另外 1023 个字节,因此在接下来的 1023 个后续读取调用中,它可以 return 直接从缓冲区中获取数据,而不必从文件中读取。
全缓冲、行缓冲和无缓冲之间的区别实际上只对输出流有影响。我很确定输入流几乎总是像完全缓冲一样。
但即使对于完全缓冲的输入流,也至少有一种情况是缓冲区不会完全满,正如您所发现的那样,输入中没有足够的字符来填充缓冲区。如果文件中只有4个字符,那么当系统去填充缓冲区时,它会得到这4个字符并将它们放入缓冲区,然后你就可以像往常一样开始取出它们了。
(只要文件包含的字符数不是缓冲区大小的精确倍数,就会出现同样的情况。例如,如果输入文件包含 1028 个字符,那么在用前 1024 个字符填充缓冲区后字符并让您读取它们,下次它填充缓冲区时,它会再次以 4 结束。)
在这种情况下,您期望它做什么?阻止等待从文件中再读取 1,020 个字符(这些字符永远不会出现)?
P.S。你说 "the stream would not be flushed until it contained 1024 bytes of stuff, right?" 但是 flushing 只是为 output 流定义的;它对输入流没有任何意义。