# C 文件讀寫
上一章我們講解了 C 語言處理的標準輸入和輸出設備。本章我們將介紹 C 程序員如何創建、打開、關閉文本文件或二進制文件。
一個文件,無論它是文本文件還是二進制文件,都是代表了一系列的字節。C 語言不僅提供了訪問頂層的函數,也提供了底層(OS)調用來處理存儲設備上的文件。本章將講解文件管理的重要調用。
## 打開文件
您可以使用 **fopen( )** 函數來創建一個新的文件或者打開一個已有的文件,這個調用會初始化類型 **FILE** 的一個對象,類型 **FILE** 包含了所有用來控制流的必要的信息。下面是這個函數調用的原型:
```
FILE *fopen( const char * filename, const char * mode );
```
在這里,**filename** 是字符串,用來命名文件,訪問模式 **mode** 的值可以是下列值中的一個:
| 模式 | 描述 |
| --- | --- |
| r | 打開一個已有的文本文件,允許讀取文件。 |
| w | 打開一個文本文件,允許寫入文件。如果文件不存在,則會創建一個新文件。在這里,您的程序會從文件的開頭寫入內容。 |
| a | 打開一個文本文件,以追加模式寫入文件。如果文件不存在,則會創建一個新文件。在這里,您的程序會在已有的文件內容中追加內容。 |
| r+ | 打開一個文本文件,允許讀寫文件。 |
| w+ | 打開一個文本文件,允許讀寫文件。如果文件已存在,則文件會被截斷為零長度,如果文件不存在,則會創建一個新文件。 |
| a+ | 打開一個文本文件,允許讀寫文件。如果文件不存在,則會創建一個新文件。讀取會從文件的開頭開始,寫入則只能是追加模式。 |
如果處理的是二進制文件,則需使用下面的訪問模式來取代上面的訪問模式:
```
"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"
```
## 關閉文件
;
為了關閉文件,請使用 fclose( ) 函數。函數的原型如下:
```
int fclose( FILE *fp );
```
如果成功關閉文件,**fclose( )** 函數返回零,如果關閉文件時發生錯誤,函數返回 **EOF**。這個函數實際上,會清空緩沖區中的數據,關閉文件,并釋放用于該文件的所有內存。EOF 是一個定義在頭文件 **stdio.h** 中的常量。
C 標準庫提供了各種函數來按字符或者以固定長度字符串的形式讀寫文件。
## 寫入文件
下面是把字符寫入到流中的最簡單的函數:
```
int fputc( int c, FILE *fp );
```
函數 **fputc()** 把參數 c 的字符值寫入到 fp 所指向的輸出流中。如果寫入成功,它會返回寫入的字符,如果發生錯誤,則會返回 **EOF**。您可以使用下面的函數來把一個以 null 結尾的字符串寫入到流中:
```
int fputs( const char *s, FILE *fp );
```
函數 **fputs()** 把字符串 **s** 寫入到 fp 所指向的輸出流中。如果寫入成功,它會返回一個非負值,如果發生錯誤,則會返回 **EOF**。您也可以使用 **int fprintf(FILE *fp,const char *format, ...)** 函數來寫把一個字符串寫入到文件中。嘗試下面的實例:
**注意:**請確保您有可用的 **/tmp** 目錄,如果不存在該目錄,則需要在您的計算機上先創建該目錄。
```
#include <stdio.h>
main()
{
FILE *fp;
fp = fopen("/tmp/test.txt", "w+");
fprintf(fp, "This is testing for fprintf...\n");
fputs("This is testing for fputs...\n", fp);
fclose(fp);
}
```
當上面的代碼被編譯和執行時,它會在 /tmp 目錄中創建一個新的文件 **test.txt**,并使用兩個不同的函數寫入兩行。接下來讓我們來讀取這個文件。
## 讀取文件
下面是從文件讀取單個字符的最簡單的函數:
```
int fgetc( FILE * fp );
```
**fgetc()** 函數從 fp 所指向的輸入文件中讀取一個字符。返回值是讀取的字符,如果發生錯誤則返回 **EOF**。下面的函數允許您從流中讀取一個字符串:
```
char *fgets( char *buf, int n, FILE *fp );
```
函數 **fgets()** 從 fp 所指向的輸入流中讀取 n - 1 個字符。它會把讀取的字符串復制到緩沖區 **buf**,并在最后追加一個 **null** 字符來終止字符串。
如果這個函數在讀取最后一個字符之前就遇到一個換行符 '\n' 或文件的末尾 EOF,則只會返回讀取到的字符,包括換行符。您也可以使用 **int fscanf(FILE *fp, const char *format, ...)** 函數來從文件中讀取字符串,但是在遇到第一個空格字符時,它會停止讀取。
```
#include <stdio.h>
main()
{
FILE *fp;
char buff[255];
fp = fopen("/tmp/test.txt", "r");
fscanf(fp, "%s", buff);
printf("1 : %s\n", buff );
fgets(buff, 255, (FILE*)fp);
printf("2: %s\n", buff );
fgets(buff, 255, (FILE*)fp);
printf("3: %s\n", buff );
fclose(fp);
}
```
當上面的代碼被編譯和執行時,它會讀取上一部分創建的文件,產生下列結果:
```
1 : This
2: is testing for fprintf...
3: This is testing for fputs...
```
首先,**fscanf()** 方法只讀取了 **This**,因為它在后邊遇到了一個空格。其次,調用 **fgets()** 讀取剩余的部分,直到行尾。最后,調用 **fgets()** 完整地讀取第二行。
## 二進制 I/O 函數
下面兩個函數用于二進制輸入和輸出:
```
size_t fread(void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);
size_t fwrite(const void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);
```
這兩個函數都是用于存儲塊的讀寫 - 通常是數組或結構體。
- C語言教程
- C 簡介
- C 環境設置
- C 程序結構
- C 基本語法
- C 數據類型
- C 變量
- C 常量
- C 存儲類
- C 運算符
- C 判斷
- C 循環
- C 函數
- C 作用域規則
- C 數組
- C 指針
- C 字符串
- C 結構體
- C 共用體
- C 位域
- C typedef
- C 輸入 & 輸出
- C 文件讀寫
- C 預處理器
- C 頭文件
- C 強制類型轉換
- C 錯誤處理
- C 遞歸
- C 可變參數
- C 內存管理
- C 命令行參數
- C語言參考
- C 標準庫 - <assert.h>
- C 庫宏 - assert()
- C 標準庫 - <ctype.h>
- C 庫函數 - isalnum()
- C 庫函數 - isalpha()
- C 庫函數 - iscntrl()
- C 庫函數 - isdigit()
- C 庫函數 - isgraph()
- C 庫函數 - islower()
- C 庫函數 - isprint()
- C 庫函數 - ispunct()
- C 庫函數 - isspace()
- C 庫函數 - isupper()
- C 庫函數 - isxdigit()
- C 標準庫 - <errno.h>
- C 庫宏 - errno
- C 庫宏 - EDOM
- C 庫宏 - ERANGE
- C 標準庫 - <float.h>
- C 標準庫 - <limits.h>
- C 標準庫 - <locale.h>
- C 庫函數 - setlocale()
- C 庫函數 - localeconv()
- C 標準庫 - <math.h>
- C 庫函數 - acos()
- C 庫函數 - asin()
- C 庫函數 - atan()
- C 庫函數 - atan2()
- C 庫函數 - cos()
- C 庫函數 - cosh()
- C 庫函數 - sin()
- C 庫函數 - sinh()
- C 庫函數 - tanh()
- C 庫函數 - exp()
- C 庫函數 - frexp()
- C 庫函數 - ldexp()
- C 庫函數 - log()
- C 庫函數 - log10()
- C 庫函數 - modf()
- C 庫函數 - pow()
- C 庫函數 - sqrt()
- C 庫函數 - ceil()
- C 庫函數 - fabs()
- C 庫函數 - floor()
- C 庫函數 - fmod()
- C 標準庫 - <setjmp.h>
- C 庫宏 - setjmp()
- C 庫函數 - longjmp()
- C 標準庫 - <signal.h>
- C 庫函數 - signal()
- C 庫函數 - raise()
- C 標準庫 - <stdarg.h>
- C 庫宏 - va_start()
- C 庫宏 - va_arg()
- C 庫宏 - va_end()
- C 標準庫 - <stddef.h>
- C 庫宏 - NULL
- C 庫宏 - offsetof()
- C 標準庫 - <stdio.h>
- C 庫函數 - fclose()
- C 庫函數 - clearerr()
- C 庫函數 - feof()
- C 庫函數 - ferror()
- C 庫函數 - fflush()
- C 庫函數 - fgetpos()
- C 庫函數 - fopen()
- C 庫函數 - fread()
- C 庫函數 - freopen()
- C 庫函數 - fseek()
- C 庫函數 - fsetpos()
- C 庫函數 - ftell()
- C 庫函數 - fwrite()
- C 庫函數 - remove()
- C 庫函數 - rename()
- C 庫函數 - rewind()
- C 庫函數 - setbuf()
- C 庫函數 - tmpfile()
- C 庫函數 - tmpnam()
- C 庫函數 - fprintf()
- C 庫函數 - printf()
- C 庫函數 - sprintf()
- C 庫函數 - vfprintf()
- C 庫函數 - vprintf()
- C 庫函數 - vsprintf()
- C 庫函數 - fscanf()
- C 庫函數 - scanf()
- C 庫函數 - sscanf()
- C 庫函數 - fgetc()
- C 庫函數 - fgets()
- C 庫函數 - fputc()
- C 庫函數 - fputs()
- C 庫函數 - getc()
- C 庫函數 - getchar()
- C 庫函數 - gets()
- C 庫函數 - putc()
- C 庫函數 - putchar()
- C 庫函數 - puts()
- C 庫函數 - ungetc()
- C 庫函數 - perror()
- C 標準庫 - <stdlib.h>
- C 庫函數 - atof()
- C 庫函數 - atoi()
- C 庫函數 - atol()
- C 庫函數 - strtod()
- C 庫函數 - strtol()
- C 庫函數 - strtoul()
- C 庫函數 - calloc()
- C 庫函數 - free()
- C 庫函數 - malloc()
- C 庫函數 - realloc()
- C 庫函數 - abort()
- C 庫函數 - atexit()
- C 庫函數 - exit()
- C 庫函數 - getenv()
- C 庫函數 - system()
- C 庫函數 - bsearch()
- C 庫函數 - qsort()
- C 庫函數 - abs()
- C 庫函數 - div()
- C 庫函數 - labs()
- C 庫函數 - ldiv()
- C 庫函數 - rand()
- C 庫函數 - srand()
- C 庫函數 - mblen()
- C 庫函數 - mbstowcs()
- C 庫函數 - mbtowc()
- C 庫函數 - wcstombs()
- C 庫函數 - wctomb()
- C 標準庫 - <string.h>
- C 庫函數 - memchr()
- C 庫函數 - memcmp()
- C 庫函數 - memcpy()
- C 庫函數 - memmove()
- C 庫函數 - memset()
- C 庫函數 - strcat()
- C 庫函數 - strncat()
- C 庫函數 - strchr()
- C 庫函數 - strcmp()
- C 庫函數 - strncmp()
- C 庫函數 - strcoll()
- C 庫函數 - strcpy()
- C 庫函數 - strncpy()
- C 庫函數 - strcspn()
- C 庫函數 - strerror()
- C 庫函數 - strlen()
- C 庫函數 - strpbrk()
- C 庫函數 - strrchr()
- C 庫函數 - strspn()
- C 庫函數 - strstr()
- C 庫函數 - strtok()
- C 庫函數 - strxfrm()
- C 標準庫 - <time.h>
- C 庫函數 - asctime()
- C 庫函數 - clock()
- C 庫函數 - ctime()
- C 庫函數 - difftime()
- C 庫函數 - gmtime()
- C 庫函數 - localtime()
- C 庫函數 - mktime()
- C 庫函數 - strftime()
- C 庫函數 - time()
- 免責聲明