文件基本操作 (C語言)


 


一切皆文件

                                                                                                                       ---Linux


  •  頭文件 <stdio.h> 中定義了文件的相關操作
#include <stdio.h>

文件操作基本流程:

打開:fopen

相關操作

關閉:fclose

fopen函數原型:FILE *fopen(const char *filename, const char *mode)

fopen函數打開filename指定的文件, 並返回一個與之相關聯的流。 如果打開操作失敗,則返回 NULL

訪問模式mode可以為下列合法值之一:

"r"          打開文本文件用於讀

"w"         創建文本文件用於寫, 並刪除已經存在的內容(如果有的話)

"a"          追加, 打開或創建文本文件,並向文件末尾追加內容

"r+"        打開文本文件用於更新(即讀和寫)

"w+"       創建文本文件用於更新, 並刪除已經存在的內容(如果有的話)

"a+"        追加, 打開或創建文本文件用於更新, 寫文件時追加到文件末尾

ps:如果在上述訪問模式之后加上 b , 如 "rb" 或 "w+b" 等,則表示對二進制文件進行操作

fclose函數原型:int fclose(FILE *fp)

fclose函數的功能是關閉 fp 指向的文件    正常關閉返回0, 出錯時返回非0

ps:文件操作結束不關閉文件可能丟失數據

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


  • 什么是文本文件?

在文本文件中數據是以字符形式呈現的,每個字符占用一個字節,而字節在計算機中又是以ASCII碼來識別的

在存儲文本文件時需要先將ASCII碼轉換為二進制的形式,然后進行存儲

比如存儲12的時候會按照字符  '1'  和  '2'  來存儲

'1' 的ASCII碼為49  轉化為二進制為 00110001      '2' 的ASCII碼為50  轉化為二進制為 00110010

存儲形式為   [00110001][00110010]

  • 什么是二進制文件?

二進制文件在存儲數據時是直接以二進制的方式進行的, 存儲方式與數據在內存中的存儲方式相同

不需要進行轉換

優點:不僅可以提高執行效率(比如從磁盤直接讀取到內存不需要數據轉換),還可以節約存儲空間

比如存儲char類型的數字12則會將其二進制數 00001100直接進行存儲

存儲i形式為   [00001100]


  • 文本文件和二進制文件的區別(Windows)

文本文件:寫入的時候會將換行符 '\n'(ASCII: 10) 解析為回車符 '\r'(ASCII:13)'\n'(ASCII:10)

                  讀取的時候又會將回車符 '\r'(ASCII:13)'\n'(ASCII:10)解析成換行符 '\n'(ASCII: 10)

二進制文件:原樣寫入讀出

  • Linux系統下沒有區別

  • 三個特殊的文件

stdin   :標准輸入文件指針,系統分配為鍵盤

stdout :標准輸出文件指針,系統分配為顯示器

stderr  :標准錯誤輸出文件指針,系統分配為顯示器

在文件操作時,系統自動與3個標准設備文件聯系,這3個文件無需打開和關閉

從文件中輸入和向文件輸出有兩個對應函數:

fprintf

函數原型為

int fprintf (FILE *, const char *, ...);

 fscanf

函數原型為

int    fscanf (FILE *, const char *, ...);

 例如 printf("hello world!\n");  等價於   fprintf(stdout, "hello world\n");

         scanf("%d", &num);  等價於    fscanf(stdin, "%d", &num);

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int main()
 5 {
 6     int num;
 7     fscanf(stdin, "%d", &num);
 8     fprintf(stdout, "%d\n", num);
 9     return 0;
10 }

  • 文件型結構體

C語言提供“文件型”結構來標識記錄待操作文件的信息,該結構體定義在頭文件 stdio.h 中

形式為:

 1 typedef struct _iobuf
 2  {
 3 char *_ptr;        /*  當前緩沖區內容指針           */
 4 int   _cnt;        /*  緩沖區還有多少個字符          */
 5 char *_base;       /*  緩沖區的起始地址             */
 6 int   _flag;       /*  文件流的狀態,是否錯誤或者結束 */
 7 int   _file;       /*  文件描述符                  */
 8 int   _charbuf;    /*  雙字節緩沖,緩沖2個字節       */
 9 int   _bufsiz;     /*  緩沖區大小                  */
10 char *_tmpfname;   /*  臨時文件名                  */
11 } FILE;

  • 文件基本操作

打開與關閉文件   fopen   fclose

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #define FILE_NAME "./1.txt"     /* 存在的文件   */
 4 #define FILE_NAME_NO "./2.txt"  /* 不存在的文件 */
 5 int main()
 6 {
 7     FILE *fp = fopen(FILE_NAME, "r");
 8     if(!fp){
 9         perror("|open file failed");
10         return 1;
11     }
12     printf("|open the file %s successfully\n", FILE_NAME);
13     int i = fclose(fp);                                     /*關閉成功返回 0*/
14     printf("|%d\n", i);
15 
16     FILE *fp_no = fopen(FILE_NAME_NO, "r");
17     if(!fp_no){
18         perror("|open file failed");
19         return 1;
20     }
21     printf("|open the file %s successfully\n", FILE_NAME_NO);
22     int j = fclose(fp_no);
23     printf("|%d\n", j);
24     return 0;
25 }

輸出

|open the file ./1.txt successfully
|0
|open file failed: No such file or directory

 


字符讀寫函數   fgetc   fputc

函數原型

1 int    fgetc (FILE *);
2 
3 int    fputc (int, FILE *);

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #define FILE_NAME "./1.txt"     /* 存在的文件   */
 4 int main()
 5 {
 6     FILE *fp = fopen(FILE_NAME, "r");
 7     if(!fp){
 8         perror("|open file failed");
 9         return 1;
10     }
11     printf("|open the file %s successfully\n", FILE_NAME);
12     char c = fgetc(fp);
13     printf("|%c\n", c);
14     fclose(fp);
15     return 0;
16 }

 輸出

|open the file ./1.txt successfully
|h

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #define FILE_NAME "./2.txt"     /* 不存在的文件   */
 4 int main()
 5 {
 6     FILE *fp = fopen(FILE_NAME, "w");
 7     if(!fp){
 8         perror("|open file failed");
 9         return 1;
10     }
11     printf("|open the file %s successfully\n", FILE_NAME);
12     fputc('h', fp);
13     fclose(fp);
14     return 0;
15 }

 新建了 2.txt文件 並寫入一個字符 h

后續的函數相關操作類似,列出了函數原型,不舉代碼示例啦(偷懶ing)

 


字符串讀寫函數  fgets      fputs

函數原型

1 int    fputs (const char *, FILE *);
2 
3 char * fgets (char *, int, FILE *);

 


格式化讀寫函數   fprintf     fscanf

函數原型

1 int fprintf (FILE *, const char *, ...);
2 
3 int fscanf (FILE *, const char *, ...);

 


數據塊讀寫函數   fread      fwrite

函數原型

1 size_t fread (void *, size_t, size_t, FILE *);
2 
3 size_t fwrite (const void *, size_t, size_t, FILE *);

這兩個函數用於讀寫數據塊,成功返回 塊數, 出錯或到文件尾返回 0

第一個參數:  指向要輸入/輸出數據塊的首地址的指針

第二個參數:  每個要讀/寫的數據塊的大小(字節數)

第三個參數:   要讀/寫的數據塊的個數

第四個參數:   要讀/寫的文件指針

fread 和 fwrite 函數一般用於 數組  結構體等塊的讀寫(多為二進制形式)

比如

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #define FILE_NAME "./3.txt"     /* 不存在的文件   */
 4 
 5 int main(){
 6 
 7     int num[50] = {0};
 8     for(int i = 0; i < 50; ++i){
 9         num[i] = i;
10     }
11     FILE *fp = fopen(FILE_NAME, "w+b");
12     fwrite(num, sizeof(int), 50, fp);
13     printf("指針到達:%d\n", (int)ftell(fp));
14     rewind(fp);
15     printf("指針到達:%d\n", (int)ftell(fp));
16     int newnum[50] = {0};
17     fread(newnum, sizeof(int), 50, fp);
18     for(int i = 0; i < 50; ++i){
19         printf(" %d", newnum[i]);
20     }
21     printf("\n");
22     fclose(fp);
23     return 0;
24 }

 得到 3.txt文件 內容:

 

可以看到一個int類型占有4個字節,並且存儲方式是低位在前高位在后

輸出結果:

 


判斷文件是否結束    feof

函數原型

int feof (FILE *);

 

feof函數用來判斷文件是否結束, 文件結束返回一個 非0值, 未結束則返回 0

 


文件出錯檢驗         ferror

函數原型

int ferror (FILE *);

 

ferror函數用來測試文件是否出錯, 未出錯返回 0, 出錯返回一個 非0值

 


文件定位       rewind    fseek   ftell

函數原型

1 int    fseek (FILE *, long, int);  /*根據參考位置靈活移動指針到目的地*/
2 
3 long   ftell (FILE *);             /*用來告訴我指針距離文件頭的字符數*/
4 
5 void   rewind (FILE *);            /*將指針重新移動到文件頭*/

 

其中 fseek函數第一個參數操作的文件指針(fp), 第二個參數是偏移量(offset) 第三個參數是參考點:0---文件開始    2---文件末尾   1---當前位置

 


刷新緩沖區    fflush

函數原型

int    fflush (FILE *);

 

對於輸出流來說, fflush函數將已經寫到緩沖區但尚未寫入文件的所有數據寫到文件中

對輸入流來說, 其結果是未定義的

如果在寫的過程中發生錯誤,則返回EOF, 否則返回 0, fflush(NULL)將清洗所有的輸出流

 


文件刪除      remove

函數原型

int    remove (const char *);

 

remove函數刪除指定的文件, 操作成功返回 0, 操作失敗返回一個 非0值

 


文件重命名    rename

函數原型

int    rename (const char *, const char *);

 

修改文件名成功返回 0 , 操作失敗返回 非0值

 


創建臨時文件    tmpfile

函數原型

FILE * tmpfile (void);

 

tmpfile函數以 "wb+" 模式創建一個臨時文件(二進制的形式-->臨時文件當然讀寫更快),該文件在被關閉或程序正常結束時將被自動刪除

創建操作成功 函數返回一個流(文件的指針), 創建文件失敗返回NULL

 


創建一個臨時文件名   tmpnam

函數原型

char * tmpnam (char *);

 

tmpnam函數創建一個與現有文件名不同的字符串,並返回一個指向一內部靜態數組的指針,tmpnam(s)函數把創建的字符串保存到數組s中,並將它作為函數返回值返回

要注意的是數組s要具有足夠的空間來存儲這個文件名字符串

示例

1 #include <stdio.h>
2  
3 int main()
4 {
5     char s[64] = {0};
6     tmpnam(s);
7     printf("%s\n", s);
8     return 0;
9 }

輸出

\s804.

這是一個隨機的文件名(只要不與現有的沖突就OK) 


后記:

-- 在進行文件操作的時候根據情況選擇合適的讀寫方式以及讀寫格式

-- 要靈活使用 feof    fflush (!!!!切記緩沖問題)    ftell      fseek     rewind     等函數

-- 文件使用結束切記 fclose 關閉文件, 避免出錯

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM