Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 完全缓冲的流在未满时被刷新_C_Buffer - Fatal编程技术网

C 完全缓冲的流在未满时被刷新

C 完全缓冲的流在未满时被刷新,c,buffer,C,Buffer,我真的搞不懂缓冲区到底是怎么工作的。所以我写了一个小片段来验证: #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("%

我真的搞不懂缓冲区到底是怎么工作的。所以我写了一个小片段来验证:

#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;
}
#包括
#定义BUF_大小1024
字符大小[buf_SIZE];
char-arr[20];
int main()
{
文件*fs=fopen(“test.txt”、“r”);
setvbuf(fs,buf,_IOFBF,1024);
fread(arr,1,1,fs);
printf(“%s”,arr);
getchar();
返回0;
}
如您所见,我将文件流
fs
设置为
完全缓冲
流(我知道大多数情况下它会默认为完全缓冲。请确保)。我还将其相关缓冲区设置为size
1024
,这意味着流在包含1024字节的内容之前不会被刷新(对吧?)

我认为,
fread()
的例行程序是,它从文件流中读取数据,将其存储在其缓冲区
buf
,然后
buf
中的数据将在充满1024字节数据时发送到
arr
(对吗?)


但是现在,我只从流中读取了一个字符!!而且,文件
test.txt
中只有四个字符。如果只有一个字符(我可以打印出那一个字符)

据我所知,输入缓冲区的工作原理与您建议的不同:如果您请求读取一个字节,系统将向缓冲区再读取1023个字节,因此,在接下来的1023次后续读取调用中,它可以直接从缓冲区返回数据,而不必从文件中读取。

完全缓冲、行缓冲和非缓冲之间的区别实际上只对输出流有影响。我很确定,输入流的行为几乎总是完全缓冲的

但即使对于完全缓冲的输入流,也至少有一种情况下缓冲区不会完全满,正如您所发现的,那就是输入中没有足够的字符来填充缓冲区。如果文件中只有4个字符,那么当系统填充缓冲区时,它会获取这4个字符并将它们放入缓冲区,然后您可以像往常一样开始取出它们

(每当文件包含的字符数不是缓冲区大小的精确倍数时,都会出现相同的情况。例如,如果输入文件包含1028个字符,则在用前1024个字符填充缓冲区并让您读取后,下次它填充缓冲区时,将再次以4个字符结束。)

你希望它在这种情况下做什么?阻止等待从文件中再读取1020个字符(这些字符永远不会出现)


另外,您说过“流在包含1024字节的内容之前不会被刷新,对吧?”但刷新只定义为输出流;它对输入流没有任何意义。

但如果文件中没有足够的字符可读取,该怎么办?我的文件只包含四个字符,我猜只有4个字节被读入缓冲区。也许在每次读取后调查缓冲区的内容(并针对不同的读取/缓冲区/文件大小进行尝试)可以帮助您更好地了解该系统的行为。实际上,我对缓冲区工作方式的看法与您的类似,也就是说,在任何I/O操作发生之前,与流相关的缓冲区都充满了来自文件的数据。或者,更具体地说,完全缓冲流的缓冲区总是自动填充来自文件的数据。如果一个字符被读出,那么另一个字符将进入…对于行缓冲流,它的缓冲区将被从流到第一个换行的数据填充character@walkerlala事实并非如此。缓冲区在第一次读取时尽可能地被填满,事实上每次都是空的。你确定刷新只意味着输出流,而不是输入流吗?我只是想验证我的猜测。根据我的理解,我猜如果没有足够的字符填充一个完全缓冲流的缓冲区,那么缓冲区中的内容就无法读取。但显然这是错误的是的,我确信输入流上的
fflush
!请看。我同意你的答案。但是,顺便问一下,
flush
在刷新输出流时做什么?是否只有在冲洗后才能使用?如果没有,为什么我们要使用flush?@walkerala:不太清楚你在问什么,但是:当你将字符写入缓冲输出流时,字符开始填满缓冲区,缓冲区实际上被写入最终输出(a)当它填满时,或者(b)当你写新行时,如果它是行缓冲的,或者(c)如果它没有缓冲,或者(d)当您关闭流时,或者(e)当您调用
fflush
时,立即启动。对于输入流,您从缓冲区读取数据,如果您尝试读取的缓冲区为空,系统将尝试填充它。如果部分满了就可以了,如果根本填不满就可以了。