Linux C高階程式設計——檔案操作之庫函式
Linux C高階程式設計——檔案操作之庫函式
宗旨:技術的學習是有限的,分享的精神是無限的
——為什麼要設計標準I/O庫?
直接使用API進行檔案訪問時,需要考慮許多細節問題
例如:read、write時,緩衝區的大小該如何確定,才能使效率最優
標準I/O庫封裝了諸多細節問題,包括緩衝區分配
——標準I/O庫緩衝
標準I/O庫提供緩衝的目的:儘可能減少使用read、write呼叫的次數,以提高I/O效率。
通過標準I/O庫進行的讀寫操作,資料都會被放置在標準I/O庫緩衝中中轉。
——緩衝型別
—全緩衝
在填滿標準I/O緩衝區後,才進行實際I/O操作(例如呼叫write函式)
呼叫fflush函式也能強制進行實際I/O操作
—行緩衝
在輸入和輸出遇到換行符時,標準I/O庫執行I/O操作
因為標準I/O庫用來收集每一行的快取的長度是固定的,所以,只要填滿了快取,即使沒有遇到新行符,也進行I/O操作
終端(例如標準輸入和標準輸出),使用行緩衝
—不帶緩衝
標準I/O庫不對字元進行緩衝儲存
標準出錯是不帶緩衝的,為了讓出錯資訊儘快顯示出來
——流的定向
對於ASCII字符集,一個字元用一個位元組表示
對於國際字符集,一個字元可用多個位元組表示
流的定向決定了所讀、寫的字元是單位元組還是多位元組的
一、開啟關閉檔案
1、fopen
——用於開啟一個指定的檔案
(1)函式原型
#include<stdio.h> FILE* fopen(const char *restrict pathname, const char *restrict type);
(2)引數
pathname:要開啟的檔名
type:指定檔案的讀、寫方式
r/rb——只讀方式開啟
w/wb——只寫,不存在則建立,使檔案長度為0
a/ab——追加
r+/r+b/rb+——讀寫開啟
W+/w+b/wb+——使檔案長度為0,讀寫而開啟
a+/a+b/ab+——在檔案尾讀和寫而開啟或建立
(3)返回值
——FILE結構指標(open返回的是檔案描述符)
2、fflush
——重新整理一個流(強制標準I/O庫進行系統呼叫,以將資料傳遞到核心)
(1)函式原型
int fflush(FILE *fp);
(2)函式引數
fp:檔案指標;若fp=NULL,則重新整理所有輸出流
(3)返回值
成功返回0,出錯返回EOF
3、fclose
——關閉一個打開了的流
(1)函式原型
int fclose(FILE *fp);
(2)函式引數和返回值
fp:要關閉的流對應的檔案指標
(3)返回值
—成功返回0,出錯返回EOF
在該檔案被關閉之前,重新整理快取中的輸出資料。快取中的輸入資料被丟棄,如果標準I/O庫已經為該流自動分配了一個快取,則釋放此快取。
二、讀寫檔案流
1、字元讀/寫檔案流
1.1、fgetc
——讀出流中的一個字元
(1)函式原型
int fgetc(FILE *fp);
(2)函式引數
fp:檔案指標
(3)返回值
成功返回讀到的內容; 出錯返回-1。
1.2、fputc
——寫一個字元到檔案流中
(1)函式原型
int fputc(int c, FILE *fp);
(2)函式引數
c:字元c
fp:檔案指標
(3)返回值
成功返回內容; 出錯返回-1
2、行讀寫檔案流(一行一行進行)——不能操作二進位制檔案
2.1、fgets
——讀出流中的一行字串
(1)函式原型
char *fgets(char *s, int n, FILE *fp);
(2)函式引數
s:字串指標,指向用來儲存所得資料的地址
n:緩衝區大小
fp:檔案指標
(3)返回值
成功返回讀到的內容到s中; 出錯返回NULL。
2.2、fputs
——寫一行字串到標準流中
(1)函式原型
int *fputs(char*s, FILE *fp);
(2)函式引數
s:以空字元結尾的字串(後接換行符)寫入標準流stdout中
fp:檔案指標
(3)返回值
成功返回非負數; 出錯返回-1。
3、塊讀寫檔案流 (fread/fwrite)
——每次I/O操作讀寫某種數量的物件,而每個物件具有指定的長度
例如,可讀寫一個二進位制陣列、結構
(1)函式原型
size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp);
size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp);
(2)引數
第一個引數ptr:用於讀寫的緩衝區
第二個引數size:每個物件的大小
第三個引數nobj:要讀寫的物件個數
第四個引數fp:檔案指標
(3)返回值
返回實際讀/寫的物件數
三、檔案流定位
1、ftell
——用於獲取當前檔案偏移量
(1)函式原型
long ftell(FILE *fp);
(2)函式引數
fp:檔案指標
(3)返回值
成功返回當前檔案偏移量; 出錯返回-1。
2、fseek
——用於設定當前檔案偏移量
(1)函式原型:
int fseek(FILE *fp, long offset, int whence);
(2)函式引數
第一個引數fp:檔案指標
第二個引數offset:相對偏移量:需結合whence才能計算出真正的偏移量
第三個引數whence:該引數取值是三個常量
SEEK_SET: 當前檔案偏移量為:距檔案開始處的offset個位元組
SEEK_CUR: 當前檔案偏移量為:當前檔案偏移量+offset(可正可負)
SEEK_END: 當前檔案偏移量為:當前檔案長度+offset(可正可負)
(3)返回值
成功返回0,出錯返回非0
3、rewind
—— 用於將檔案偏移量設定到檔案的起始位置
(1)函式原型
void rewind(FILE *fp);
(2)函式引數
fp:檔案指標
(3)返回值
無
// 小程式:用標準庫函式實現檔案拷貝功能:
#include<stdio.h>
//#include<string.h>
#include<stdlib.h>
void file_copy(char *fd, char *fp);
int main(intargc, char **argv)
{
file_copy(argv[1], argv[2]);
return 0;
}
void file_copy(char *fd, char *fp)
{
FILE *from_fd, *to_fd;
int ret, file_len; //定義檔案大小
char buffer[1024];//緩衝區
if((from_fd = fopen(fd, "rb")) == NULL) //開啟目標檔案
{
printf("file openfail!\n");
exit(1);
}
if((to_fd = fopen(fp, "wb")) == NULL) //建立新檔案
{
printf("file openfail!\n");
exit(0);
}
fseek(from_fd, 0L, SEEK_END);
file_len = ftell(from_fd);//計算檔案大小
fseek(from_fd, 0L, SEEK_SET);
if((ret = fread(buffer, file_len, 1, from_fd)) == -1) //讀取檔案到buffer中,返回實際讀到的物件個數(不是讀取的位元組數)
{
printf("file readfail!\n");
exit(0);
}
//printf("!!!!!!!!!!!%d\n",ret);
fwrite(buffer, file_len, 1, to_fd); //把buffer裡面的內容寫到新檔案中
fclose(from_fd);
fclose(to_fd);//關閉檔案
}