标準I/O庫提供緩沖的目的是盡可能地減少使用read和write調用的次數。它也對每個I/O流自動地進行緩沖管理,進而避免了應用程式需要考慮這一點所帶來的麻煩。不幸的是,标準I/O庫最令人迷惑的也是它的緩沖。
标準I/O提供了三種類型的緩沖:
1、全緩沖:
在填滿标準I/O緩沖區後才進行實際I/O操作。正常檔案(如普通文本檔案)通常是全緩沖的。
2、行緩沖:
當在輸入和輸出中遇到換行符時,标準I/O庫執行I/O操作。這允許我們一次輸出一個字元,但隻有在寫了一行之後才進行實際I/O操作。标準輸入和标準輸出對應終端裝置(如螢幕)時通常是行緩沖的。
3、不帶緩沖:
使用者程式每次調庫函數做寫操作都要通過系統調用寫回核心(如系統調用函數)。标準錯誤輸出通常是無緩沖的,這樣使用者程式産生的錯誤資訊可以盡快輸出到裝置。
下面是各個緩沖區的驗證。
全緩沖:
int main(int argc, char *argv[])
{
FILE *fp = NULL;
// 讀寫方式打開,檔案不存在則建立
fp = fopen("sunplusedu.txt", "w+");
if(NULL == fp)
{
printf("open error\n");
return 1;
}
char *str = "sunplusedu\n";
fwrite(str, 1, strlen(str), fp); // 往檔案寫内容
while(1); // 程式阻塞在這裡
return 0;
}
運作程式發現,sunplusedu.txt并沒有内容。因為正常檔案通常是全緩沖的,隻有緩沖區滿了後,才會把内容寫到檔案中。接下來,我們改一下上面那個例子。
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *fp = NULL;
// 讀寫方式打開,檔案不存在則建立
fp = fopen("sunplusedu.txt", "w+");
if(NULL == fp)
{
printf("open error\n");
return 1;
}
char *str = "sunplusedu\n";
int i = 0;
while(i <= 512){ // 緩沖區大小不确定,i的大小隻是一個調試值
fwrite(str, 1, strlen(str), fp); // 往檔案寫内容
i++;
}
while(1); // 程式阻塞在這裡
return 0;
}
上面的例子是循環給檔案寫内容,讓緩沖區有填滿的可能,結果發現,檔案是有内容的。實際上要想成功給檔案寫進内容,除了緩沖區填滿,還有别的方法。
1)人為關閉檔案,就算緩沖區沒有填滿,内容也會寫進檔案
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *fp = NULL;
// 讀寫方式打開,檔案不存在則建立
fp = fopen("sunplusedu.txt", "w+");
if(NULL == fp)
{
printf("open error\n");
return 1;
}
char *str = "sunplusedu\n";
fwrite(str, 1, strlen(str), fp); // 往檔案寫内容
fclose(fp); // 人為關閉檔案,就算緩沖區沒有填滿,内容也會寫進檔案
while(1); // 程式阻塞在這裡
return 0;
}
2)程式正常結束,就算緩沖區沒有填滿,沒有關閉檔案,内容也會寫進檔案。
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *fp = NULL;
// 讀寫方式打開,檔案不存在則建立
fp = fopen("sunplusedu.txt", "w+");
if(NULL == fp)
{
printf("open error\n");
return 1;
}
char *str = "sunplusedu\n";
fwrite(str, 1, strlen(str), fp); // 往檔案寫内容
return 0;
// 程式正常結束,就算緩沖區沒有填滿,沒有關閉檔案,内容也會寫進檔案。
}
行緩沖:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("hello sunplusedu");
while(1);
return 0;
}
運作這個程式,會發現 hello sunplusedu 并沒有列印到螢幕上。因為标準輸入和标準輸出對應終端裝置時通常是行緩沖的,當在輸入和輸出中遇到換行符時,标準I/O庫執行I/O操作。如下:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("hello sunplusedu\n");
while(1);
return 0;
}
除了遇到換行符,還有别的方法可以執行I/O操作。
1)緩沖區填滿
int main(int argc, char *argv[])
{
while(1){ // 循環列印,總有緩沖區填滿的可能
printf("hello sunplusedu");
}
while(1);
return 0;
}
2)人為重新整理緩沖區
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("hello sunplusedu");
fflush(stdout); // 人為重新整理
while(1);
return 0;
}
3)程式正常結束
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("hello sunplusedu");
return 0;
// 程式正常結束
}
不帶緩沖:
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *str = "hello sunplusedu.com";
// 有沒有\n,緩沖區有沒有填滿,都沒關系
write(1, str, strlen(str)); // 往标準輸出寫内容
while(1);
return 0;
}