IO
1.概念
- IO指input/output
- Linux中一切皆文件
- IO的操作對象是文件
2.文件
-
一段數據的集合
-
文件通常存放在外存中,掉電后數據不丟失
-
分類
-
b(block,塊設備文件)
按塊掃描信息的文件。通常存儲類型的設備為塊設備文件。文件IO
-
c(character,字符設備文件)
按字符掃描信息的文件,一般設備通常為字符設備文件。文件IO
-
d(directory,目錄文件)
目錄文件,存放文件的文件夾。目錄IO/文件IO
-
-(普通文件)
存放信息。標準IO,文件IO
-
l(link,鏈接文件)
操作文件等價于操作文件指向的文件。鏈接IO/文件IO
-
s(socket,套接字文件)
用來進程間通信。文件IO
-
p(pipe,管道文件)
用來進程間通信。文件IO
-
3.標準IO
- 通常用來操作普通文件
1.普通文件類型
- ASCII碼文件:文件中的所有內容均為能夠在屏幕上顯示的ASCII碼字符
- 程序,文本文件均為ASCII碼文件
- 二進制文件:文件中的所有內容均為數據對應的二進制形式存放(包含一些不能再界面上顯示的內容)
- ASCII碼文件也是二進制文件
- 圖片,音視頻,壓縮包均為二進制文件
2.標準IO接口
- fopen/fclose
- fgetc/fputc
- fgets/fputs
- fscanf/fprintf
- fread/fwrite
- fseek/rewind/ftell
- 操作步驟:打開,讀寫,關閉
3.文件的打開
函數接口
-
fopen
原型:FILE *fopen(const char *pathname, const char *mode); 功能:打開pathname指向字符串對應的文件,并和他建立一個流 參數:pathname:要打開的文件路徑字符串mode:打開方式r 只讀 文件存在只讀打開,文件不存在報錯r+ 讀寫 文件存在讀寫打開,文件不存在報錯w 只寫 文件存在清0,文件不存在創建,只寫打開w+ 寫讀 文件存在清0,文件不存在創建,寫讀打開a 追加 文件存在追加,文件不存在創建,只寫打開a+ 追加讀寫 文件存在追加,文件不存在創建,寫讀打開 返回值:成功返回FILE*指針失敗返回NULL
-
fclose
原型:int fclose(FILE *stream); 功能:關閉已經打開的流 參數:stream:文件流指針 返回值:成功返回0失敗返回EOF(-1)
-
fputc
原型:int fputc(int c, FILE *stream); 功能:將字符c寫入流中 參數:c:要寫入的字符stream:文件流指針 返回值:成功返回輸出的ASCII碼值失敗返回EOF
- putchar()等價于fputc(ch,stdout)
-
fgetc
原型:int fgetc(FILE *stream); 功能:讀取流中的下一個字符 參數:stream:文件流指針 返回值:成功返回讀到字符的ASCII碼值失敗或者讀到文件末尾返回EOF
- ch = getchar()等價于ch = fgetc(stdin)
-
fputs
原型:int fputs(const char *s,FILE *stream); 功能:向流中寫入s指向的字符串 參數:s:寫入的字符串的首地址stream:文件流指針 返回值:成功返回非負數失敗返回EOF
- fputs不會多打印\n字符
- puts會多打印一個\n字符
-
fgets
原型:char *fgets(char *s, int size, FILE *stream); 功能:從流中最多讀size個字節數據放入s指向的空間中,遇到\n讀取截止 參數:s:寫入字符串的首地址size:最多存放元素的個數stream:文件流指針 返回值:成功返回存放數據空間的首地址失敗返回NULL讀到文件末尾返回NULL
- gets會去掉從終端接收的\n字符
- fgets不會去掉,并在最后加\0
-
fprintf
原型:int fprintf(FILE *stream, const char *format, ...); 功能:將格式化的字符串打印在流中 參數:stream:文件流指針format:格式化的字符串...:參數 返回值:成功返回打印字符的個數失敗返回負數
-
fscanf
原型:int fscanf(FILE *stream, const char *format, ...); 功能:從流中接收格式化的字符串 參數:stream:文件流指針format:格式化的字符串...:參數 返回值:成功返回匹配的輸入控制符的個數失敗返回EOF讀到末尾返回EOF
練習1:
-
從終端接收一個文件名,在終端打印出他的行數
#include<stdio.h> #include<string.h> #include<error.h>int get_line(char *pfile){int cnt = 1;FILE *fp = fopen(pfile,"r");char ch = 0;fp = fopen(pfile,"r");if(fp == NULL){perror("fail to fopen");return -1;}while(1){ch = fgetc(fp);if(ch == '\n'){cnt++;}if(EOF == ch){break;}}fclose(fp);return cnt; }int main(void){char filepath[256] = {0};int line = 0;printf("請輸入文件名:"); gets(filepath);line = get_line(filepath);printf("有%d行\n",line);return 0; }
-
將一個文件的內容拷貝到另一個文件中
#include<stdio.h> #include<string.h> #include<error.h>int main(void){char filename[100] = {0};char filename2[100] = {0};FILE* fp = NULL;FILE*fp2 = NULL;char ch = 0;printf("輸入源文件名:");gets(filename);fp = fopen(filename,"r");if(fp == NULL){perror("fail to open");return -1;}printf("輸入新文件名:");gets(filename2);fp2 = fopen(filename2,"w");if(fp2 == NULL){perror("fail to open");return -1;}while(1){ch = fgetc(fp);if(EOF == ch){break;}fputc(ch,fp2);}fclose(fp);fclose(fp2);return 0;}
已經打開的三個特殊的流
-
stdin:標準輸入流
scanf,gets,getchar都是通過stdin流實現獲得終端信息
-
stdout:標準輸出流
printf,puts,putchar都是通過stdout流實現在終端信息打印
-
stderr:標準出錯流
perror通過stderr流實現在終端打印出錯信息
4.標準IO的緩存
- 效率高,實時性差
1.緩存類型
-
全緩存
緩存區滿刷新緩存
刷新條件:
-
緩存區滿4k刷新
-
fflush函數強制刷新
-
fclose或者程序關閉刷新
與文件建立的緩存一般為全緩存
-
-
行緩存
遇到\n刷新緩存區
刷新條件:
- 緩存區滿1k刷新
- fflush函數強制刷新
- fclose或者程序關閉刷新
- 遇到\n刷新
與終端建立的緩存一般為行緩存(stdin,stdout均為行緩存)
-
不緩存
立即刷新不緩存
刷新條件:
- 不緩存立即刷新
出錯處理或者人機交互一般使用不緩存
習題
1.利用fgets和fputs實現文件內容的拷貝
代碼實現:
#include<stdio.h>
#include<string.h>void copyfile(char *src,char *dst){FILE *srcfile = NULL;FILE *dstfile = NULL;char ch[1024] = {0};srcfile = fopen(src,"r");if(srcfile == NULL){printf("打開源文件失敗!\n");return;}dstfile = fopen(dst,"w");if(dstfile == NULL){printf("打開目標文件失敗!\n");fclose(srcfile);return;}while(fgets(ch,sizeof(ch),srcfile) != NULL){fputs(ch,dstfile);}fclose(srcfile);fclose(dstfile);return;
}int main(void){char srcfile[100] = {0};char dstfile[100] = {0};printf("請輸入源文件:");fgets(srcfile,sizeof(srcfile),stdin);srcfile[strlen(srcfile) - 1] = 0;printf("請輸入目標文件:");fgets(dstfile,sizeof(dstfile),stdin);dstfile[strlen(dstfile) - 1] = 0;copyfile(srcfile,dstfile);return 0;
}
2.從終端接受數字,將數字存放在文件中,程序實時顯示當前所有數字的平均數,如果程序關閉再次啟動時能夠顯示之前用戶輸入的所有數字的平均值
代碼實現:
#include<stdio.h>int main(void){FILE *fp = NULL;int sum = 0;int num = 0;int count = 0;float average = 0;fp = fopen("number.txt","a+");if(fp == NULL){perror("fail to fopen");return -1;}while(fscanf(fp,"%d",&num) == 1){sum += num;count++;}while(1){fprintf(stdout,"請輸入一個數字:");fscanf(stdin,"%d",&num);if(num < 0) {fprintf(stdout, "輸入結束,程序退出。\n");break;}fprintf(fp,"%d\n",num);sum += num;count++;average = (float)sum / count;fprintf(stdout,"%f\n",average);}fclose(fp);return 0;
}