目錄
1.文件的順序讀寫
2.文件的隨機讀寫
3.文件讀取結束的判定
4.文件的緩沖區
1.文件的讀取順序
1.1 順序讀寫函數介紹
上面說的適用于所有輸入流一般指適用于標準輸入流和其他輸入流(如文件輸入流);所有輸出流
一般指適用于標準輸出流和其他輸出流(如文件輸出流)。
1.2 對比一組函數
- scanf/fscanf/sscanf
- printf/fprintf/sprintf
scanf/fscanf/sscanf:
?
- scanf
- 功能:從標準輸入流(通常是鍵盤)讀取數據 ,按照指定格式進行解析并存儲到對應變量中。例如?scanf("%d", &num);??,從鍵盤讀取一個整數存入?num?變量。
- 特點:直接從標準輸入獲取數據,使用方便,但要注意輸入格式與指定格式嚴格匹配,否則可能導致輸入錯誤或程序異常。
- fscanf
- 功能:從指定的文件輸入流中讀取數據,按格式解析存儲。如?fscanf(fp, "%d", &num);??,從文件指針?fp?指向的文件中讀取整數存到?num??。
- 特點:用于文件數據讀取,可靈活處理文件中不同格式數據,但要先正確打開和操作文件。
- sscanf
- 功能:從字符串中讀取數據,按格式解析存儲。比如?sscanf(str, "%d", &num);??,從字符串?str?中提取整數存到?num??。
- 特點:在處理已存在字符串中的數據時很有用,可方便地從字符串提取不同類型數據。
?
printf/fprintf/sprintf:
?
- printf
- 功能:向標準輸出流(通常是控制臺)按照指定格式輸出數據。像?printf("The number is %d", num);??,在控制臺顯示變量?num?的值。
- 特點:是最常用的輸出方式,能快速將數據展示在屏幕上。
- fprintf
- 功能:向指定文件輸出流寫入數據,按格式輸出。例如?fprintf(fp, "The number is %d", num);??,將數據寫入文件指針?fp?指向的文件。
- 特點:用于文件數據寫入,可將程序數據按格式保存到文件中。
- sprintf
- 功能:將格式化數據寫入字符串中。如?sprintf(str, "The number is %d", num);??,把數據按格式存入字符串?str??。
- 特點:常用于字符串格式化構建,方便生成特定格式字符串用于后續處理。
2.文件的隨機讀寫
2.1 fseek
根據文件指針的位置和偏移量來定位文件指針(文件內容的光標)。
int fseek ( FILE * stream, long int offset, int origin );
例子:
/* fseek example */
#include <stdio.h>int main ()
{FILE * pFile;pFile = fopen ( "example.txt", "wb" );fputs ( "This is an apple.", pFile );fseek ( pFile, 9, SEEK_SET );fputs ( "sam", pFile );fclose ( pFile );return 0;
}
2.2 ftell
返回文件指針相對于起始位置的偏移量
long int ftell ( FILE * stream );
例子:
/* ftell example : getting size of a file */
#include <stdio.h>int main ()
{FILE * pFile;long size;pFile = fopen ("myfile.txt","rb");if (pFile==NULL)perror ("Error opening file");else{fseek (pFile, 0, SEEK_END); // non-portablesize=ftell (pFile);fclose (pFile);printf ("Size of myfile.txt: %ld bytes.\n",size);}return 0;
}
2.3 rewind
讓文件指針的位置回到文件的起始位置
void rewind ( FILE * stream );
例子:
/* rewind example */
#include <stdio.h>int main ()
{int n;FILE * pFile;char buffer [27];pFile = fopen ("myfile.txt","w+");for ( n='A' ; n<='Z' ; n++)fputc ( n, pFile);rewind (pFile);fread (buffer,1,26,pFile);fclose (pFile);buffer[26]='\0';printf(buffer);return 0;
}
3.文件讀取結束的判定
3.1 被錯使用的feof
牢記: 在文件讀取過程中, 不能用 feof 函數的返回值直接來判斷文件的是否結束。
feof 的作用是: 當文件讀取結束的時候, 判斷讀取結束的原因是否是: 遇到文件尾結束。
1.?文本文件讀取是否結束,判斷返回值是否為 EOF(fgetc),或者 NULL(fgets)
例如:
- fgetc 判斷是否為 EOF .
- fgets 判斷返回值是否為 NULL .
?
2.?二進制文件的讀取結束判斷,判斷返回值是否小于實際要讀的個數。
例如:
?- fread判斷返回值是否小于實際要讀的個數。
?文本文件的例子:
#include <stdio.h>
#include <stdlib.h>int main(void)
{int c; // 注意: int,非char, 要求處理EOFFILE* fp = fopen("test.txt", "r");if(!fp) {perror("File opening failed");return EXIT_FAILURE;}//fgetc 當讀取失敗的時候或者遇到文件結束的時候,都會返回EOFwhile ((c = fgetc(fp)) != EOF) // 標準C I/O讀取文件循環{putchar(c);}//判斷是什么原因結束的if (ferror(fp))puts("I/O error when reading");else if (feof(fp))puts("End of file reached successfully");fclose(fp);
}
二進制文件的例子:
#include <stdio.h>enum { SIZE = 5 };int main(void)
{double a[SIZE] = {1.,2.,3.,4.,5.};FILE *fp = fopen("test.bin", "wb"); // 必須用二進制模式fwrite(a, sizeof *a, SIZE, fp); // 寫double的數組fclose(fp);double b[SIZE];fp = fopen("test.bin", "rb");size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 讀double的數組if(ret_code == SIZE) {puts("Array read successfully, contents: ");for(int n = 0; n < SIZE; ++n)printf("%f ", b[n]);putchar('\n');} else { // error handlingif (feof(fp))printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) {perror("Error reading test.bin");}}fclose(fp);
}
4.文件緩沖區
ANSI C標準采用“緩沖文件系統”處理數據文件的,所謂緩沖文件系統是指系統自動地在內存中為程
序中每一個正在使用的文件開辟一塊“文件緩沖區”。從內存向磁盤輸出數據會先送到內存中的緩沖
區,裝滿緩沖區后才一起送到磁盤上。如果從磁盤向計算機讀入數據,則從磁盤文件中讀取數據輸
入到內存緩沖區(充滿緩沖區),然后再從緩沖區逐個地將數據送到程序數據區(程序變量等)。
緩沖區的大小根據C編譯系統決定的。
#include <stdio.h>
#include <windows.h>
//VS2022 WIN11環境測試
int main()
{FILE*pf = fopen("test.txt", "w");fputs("abcdef", pf);//先將代碼放在輸出緩沖區printf("睡眠10秒-已經寫數據了,打開test.txt文件,發現文件沒有內容\n");Sleep(10000);printf("刷新緩沖區\n");fflush(pf);//刷新緩沖區時,才將輸出緩沖區的數據寫到文件(磁盤)//注: fflush 在高版本的VS上不能使用了printf("再睡眠10秒-此時,再次打開test.txt文件,文件有內容了\n");Sleep(10000);fclose(pf);//注: fclose在關閉文件的時候,也會刷新緩沖區pf = NULL;return 0;
}
這里可以得出一個結論:
因為有緩沖的存在,C語言在操作文件的時候,需要做刷新緩沖區或者在文件操作結束的時候關閉文
件,如果不做,可能導致讀寫文件的問題。
關于文件操作的所有內容到這就已經完了,下期我們講解編譯和鏈接部分相關的內容,感謝大家的
觀看!