標準I/O與文件I/O的區別:
文件操作:
? ? ? ? ?緩存 ? ? ? ? ? 操作對象 ? ? ? ? ? ? ? ?具體操作
標準IO ?全緩存/行緩存 ? 文件指針(流指針)FILE * ?1.打開 --fopen ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2.讀寫?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ?fgetc/fputc?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ?fgets/fputs?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ?fread/fwrite?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? ?3.關閉?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ?fclose?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?4.定位?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ?fseek/ftell/rewind?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ?
文件IO ?不帶緩存 ? ? ? ?文件描述符 (整數) ? ? ? 1.打開 --open?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2.讀寫 --read/write
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?3.關閉 --close?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?4.定位 --lseek?
特性:
? ? ? ? .1 沒有緩存區 (//可以認為數據直接交給了內核 )
?? ??? ?.2 操作對象不在是流(FILE *),而是文件描述符(整數)
?? ??? ?.3文件描述符
?? ??? ? ?很小的非負的整數?? ?int ? 0-1023
?? ??? ? ?內核每打開一個文件就會獲得一個文件?? ?描述符? ?
?????????每個程序在啟動的時候操作系統默認為其打開
?? ??? ? ???三個描述符與流對象匹配:
?? ??? ? ??????0 ==>STDIN_FILENO === stdin
?? ??? ? ???? ?1 ==>STDOUT_FILENO == stdout
?? ??? ? ??????2 ==>STDERR_FILENO == stderr
? ? ??
?? ??? ? ?stdin,stdout,stderr,===>FILE*
優缺點:
標準I/O:
優點:
- 緩沖:標準I/O使用了緩沖區,可以減少對文件的直接訪問,提高性能。
- 格式化輸出:標準I/O函數如
printf
和scanf
提供了強大的格式化功能,可以方便地處理格式化輸入輸出。 - 跨平臺:標準I/O函數在大多數操作系統上都是可用的,提高了代碼的可移植性。
缺點:
- 性能:與文件I/O相比,標準I/O可能會有額外的性能開銷,因為它包含了額外的緩沖和格式化處理。
- 復雜性:標準I/O函數可能比文件I/O函數更復雜,需要更多的參數和錯誤處理。
文件I/O:
優點:
- 性能:文件I/O直接操作文件描述符,沒有額外的緩沖和格式化處理,因此通常比標準I/O更快。
- 靈活性:文件I/O提供了更多的控制和靈活性,允許程序員直接操作文件和文件描述符。
- 無緩沖:文件I/O可以直接讀寫文件,無需緩沖區,這使得它可以用于處理非常大的文件或需要實時處理的數據。
缺點:
- 復雜性:文件I/O函數通常比標準I/O函數更復雜,需要更多的參數和錯誤處理。
- 格式化:文件I/O不提供格式化功能,需要程序員手動處理數據格式。
- 跨平臺:文件I/O函數在不同的操作系統上可能有不同的行為,這降低了代碼的可移植性。
一般在沒有特殊要求的情況下,在linux下優先選擇文件I/O
open()
1.open
?? ??? ?open("1.c",O_WRONLY|O_CREAT,0666 );
?? ??? ?
?? ??? ?int open(const char *pathname, int flags,int mode);
?? ??? ?功能:
?? ??? ??? ?獲得一個文件描述符
?? ??? ?參數:
?? ??? ??? ?pathname:文件名
?? ??? ??? ?flags:
?? ??? ??? ?必須項:他們之間是互斥的,所以有且只能有一個?
?? ??? ??? ??? ?O_RDONLY
?? ??? ??? ??? ?O_WRONLY
?? ??? ??? ??? ?O_RDWR
?? ??? ??? ?可選項:
?? ??? ??? ?O_CREAT, 創建文件 ?//這個標志量存在,則需要指定參數 mode
?? ??? ??? ?O_EXCL, ?需要和O_CREAT同時使用,表示新建的文件不存在,成功,否則open就會失敗
?? ??? ??? ?O_TRUNC ?文件內容清空
?? ??? ??? ?O_APPEND追加
?? ??? ??? ?
?? ? ? ? ? ?//后面
?? ??? ??? ?O_NOCTTY,不是終端設備
?? ??? ??? ?O_ASYNC 異步io,什么時候io不確定,
?? ??? ??? ?O_NONBLOCK 非阻塞?
一般在創建文件時,都加入截斷操作,標準io中w=O_CREAT | O_WRONLY | O_TRUNC
write()
?? ?2.write
?? ??? ?char buf[1024];
?? ??? ?ssize_t write(int fd, ?const ?void *buf, size_t count);
?? ??? ?功能:
?? ??? ??? ?通過文件描述符向文件中寫一串數據
?? ??? ?參數:
?? ??? ??? ?fd:文件描述符
?? ??? ??? ?buf:要寫入文件的字符串的首地址
?? ??? ??? ?count:要寫入字符的個數
?? ??? ?返回值:?
?? ??? ??? ?成功返回實際寫入的個數
?? ??? ??? ?失敗返回-1
read()
3.read
?? ??? ?ssize_t read(int fd, void *buf, size_t count);
?? ??? ?功能:
?? ??? ??? ?通過文件描述符讀取文件中的數據
?? ??? ?參數:
?? ??? ??? ?fd:文件描述符
?? ??? ??? ?buf:存放數據空間的首地址
?? ??? ??? ?count:要讀到數據的個數
?? ??? ?返回值:
?? ??? ??? ?成功返回讀到數據的個數
?? ??? ??? ?失敗返回-1
?? ??? ??? ?讀到文件結尾返回0
lssek()
4.lseek? ==? fseek, rewind ftell
?? ??? ?off_t lseek(int fd, off_t offset, int whence);
?? ??? ?功能:
?? ??? ??? ?定位文件的位置
?? ??? ?參數:
?? ??? ??? ?fd:文件描述符
?? ??? ??? ?offset:偏移量
?? ??? ??? ??? ??? ??? ?正:向后偏移
?? ??? ??? ??? ??? ??? ?負:向前偏移
?? ??? ??? ??? ??? ??? ?零:不偏移
?? ??? ??? ?whence:
?? ??? ??? ??? ?SEEK_SET
?? ??? ??? ??? ?SEEK_CUR
?? ??? ??? ??? ?SEEK_END
?? ??? ??? ??? ? ? ? ? ? 正 空洞?
?? ??? ?返回值:
?? ??? ??? ?成功返回偏移量
?? ??? ??? ?失敗返回-1
?? ??? ??? ?lseek(fd,0,SEEK_END);
文件描述符與流指針的轉換:
filino:
int fileno(FILE *stream);
功能:
?? ?獲得一個文件流指針中的文件描述符
參數:
?? ?stream:文件流指針
返回值:
?? ?成功返回文件描述符
?? ?失敗返回-1
fdopen:
2.fdopen?? ?int fd -> FILE *fp
?FILE *fdopen(int fd, const char *mode);
?功能:
?? ?將文件描述符轉化為文件流指針
?參數:
?? ?fd:已經打開的文件描述符
?? ?mode:
?? ??? ?"r"
?? ??? ?"r+"
?? ??? ?"w"
?? ??? ?"w+"
?? ??? ?"a"
?? ??? ?"a+"
?返回值:
?? ?成功返回文件流指針
?? ?失敗返回NULL?? ?