open:系統調用,返回的是文件描述符,即文件句柄,是文件在文件描述副表里的索引。
fopen:C語言庫函數,返回的是一個指向文件結構的指針。fopen是ANSI C標準中的C語言庫函數,在不同的操作系統中應該調用不同的內核API,UNIX環境下,fopen是對open的封裝。
文件描述符是UNIX/Linux下的一個概念,Linux環境下,一切設備皆是文件,一切設備皆是以文件的形式進行操作,如網絡套接字、硬件設備等。
設備文件不可以當成流式文件來處理,因此,只能使用open,而fopen只是用來操縱正規文件的,并且設置有緩沖,跟open還是有區別的。
open和fopen的區別在于:
1.緩沖文件系統
緩沖文件系統是借助于文件結構體指針FILE *來對文件進行管理,通過文件指針對文件進行訪問,即可以讀寫字符、字符串、格式化數據,也可以讀寫二進制數據。
緩 沖文件系統特點:在內存中開辟一個“緩沖區”,為程序里每一個文件使用,當執行讀文件操作時,從磁盤文件將數據先讀入內存“緩沖區”,裝滿后再從內存“緩沖區”依次讀入接收的變量。執行寫文件操作時,也是先將數據寫入內存“緩沖區”,待內存“緩沖區”裝滿后再寫入文件。由此可以看出,內存“緩沖區”的大 小,影響著實際操作外在的次數,內存“緩沖區”越大,則操作外存的次數就越少,執行速度就越快,效率就越高。一般來說,文件“緩沖區”的大小跟機器是相關的。
緩沖文件系統的IO函數主要包括:fopen, fclose, fread, fwrite, fgetc,fgets, fputc, fputs, freopen, fseek, ftell, rewind等。
2.非緩沖文件系統
非緩沖文件系統依賴于操作系統,通過操作系統的功能對文件進行讀寫,是系統級的輸入輸出,它不設文件結構體指針,只能讀寫二進制文件(對于UNIX系統內核而言,文本文件和二進制代碼文件并無區別),但效率高、速度快,由于ANSI標準不再包括非緩沖文件系統,因此,在讀取正規的文件時,建議大家最好不要選擇它。
非緩沖文件系統的IO函數主要包括:open, close, read, write, getc,getchar, putc, putchar等。
兩者的區別:
- fopen 系列是標準的C庫函數;open系列是 POSIX 定義的,是UNIX系統里的systemcall。
也就是說,fopen系列更具有可移植性;而open系列只能用在 POSIX 的操作系統上。 - 使用fopen 系列函數時要定義一個指代文件的對象,被稱為“文件句柄”(filehandler),是一個結構體;而open系列使用的是一個被稱為“文件描述符” (file descriptor)的int型整數。
- fopen 系列是級別較高的I/O,讀寫時使用緩沖;而open系列相對低層,更接近操作系統,讀寫時沒有緩沖。由于能更多地與操作系統打交道,open系列可以訪問更改一些fopen系列無法訪問的信息,如查看文件的讀寫權限。這些額外的功能通常因系統而異。
- 使用fopen系列函數需要"#include<sdtio.h>";使用open系列函數需要"#include <fcntl.h>" ,鏈接時要之用libc(-lc)
小結:
總的來說,為了使程序獲得更好的可移植性,未到非得使用一些fopen系列無法實現的功能的情況下,fopen系列是首選。
函數原型:
FILE fopen(constchar filename,constchar* mode );
filename 是字符串,用來命名文件,mode 為訪問模式的值
int fclose( FILE *fp );
如果成功關閉文件,fclose( ) 函數返回零,如果關閉文件時發生錯誤,函數返回 EOF。
size_t fread(void *ptr, size_tsize_of_elements, size_tnumber_of_elements, FILE *a_file);
size_t fwrite(constvoid *ptr, size_tsize_of_elements, size_tnumber_of_elements, FILE *a_file);
文件描述符和文件指針的區別
文件描述符就是open文件時產生的一個整數,一般用fd表示,其實就是一個索引,在UNIX系統中,用來標識文件。
文件指針是是一個指向FILE的結構體,在這個結構體當中,文件描述符是它的元素之一。它用于ANSI C標準的IO庫調用中,用來標識文件。
因為FILE結構體中包含了文件描述符,所以我們在調用open() 打開一個文件的時候,會通過來這個open來獲得文件描述符fd。
對于一個文件來說,它的文件描述符是唯一的,但是它的文件指針卻不是唯一的,只是這些指針指向的對象是唯一的,也就是這個文件。
FILE *中除了包含了fd信息,還包含了IO緩沖,所以可以理解為FILE是對fd的封裝,是C標準形式,所以FILE *比fd更適合跨平臺,一般情況下優先選擇fopen。
C語言文件指針與文件描述符之間可以相互轉換:
int fileno(FILE *stream);
FILE *fdopen(int fd, const char *mode);