解析標(biāo)準(zhǔn)IO中對文件的基本操作
對于Linux程序員來說,對文件的IO操作是應(yīng)用編程的基礎(chǔ)內(nèi)容,也是必須掌握的技能;下面作者通過兩個基本概念和四個函數(shù),來解析對文件的基本操作;
首先要明白兩個基本的概念;文件和IO;
1.文件:文件指的是同類型數(shù)據(jù)的集合; 在linux中有一個重要思想;一切皆文件;也是說在Linux系統(tǒng)中把所有的文件、設(shè)備、內(nèi)存等都當(dāng)做文件來看待;因為這個思想的存在,所有在Linux系統(tǒng)中對設(shè)備及文件的操作方式都是一樣的。Linux中把文件分為七種類型,分別是普通文件、設(shè)備文件(塊設(shè)備和字符設(shè)備)、目錄文件、管道文件、鏈接文件(符號鏈接文件),套接字;我們主要以普通文件來學(xué)習(xí);
2. IO: IO是input和output的簡寫,也就是指的輸入和輸出;對于Linux系統(tǒng)來講;輸入及輸出主要是從程序的角度來看的,因為程序員的主要的工作就是使用程序來處理數(shù)據(jù); 所以輸入指的就是把數(shù)據(jù)輸入到程序中,輸出值指的是從程序中輸出數(shù)據(jù);一般情況下,輸入主要使用鍵盤,鍵盤也叫標(biāo)準(zhǔn)輸入,而輸出的結(jié)果主要顯示在屏幕上,屏幕也就是標(biāo)準(zhǔn)輸出;除了標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出外,還有一個標(biāo)準(zhǔn)文件——標(biāo)準(zhǔn)錯誤輸出,它指的是當(dāng)程序與運行或出錯時,結(jié)果也會顯示到屏幕上; 實際中,我們的數(shù)據(jù)輸入并不一定要從鍵盤中輸入,輸出也不是只能輸出到屏幕上;我們可以從文件、內(nèi)存中輸入數(shù)據(jù)到程序,也可以從程序中輸出數(shù)據(jù)到文件及內(nèi)存中;
在此文中,輸入/輸出都是對文件而言;
了解上面兩個概念的有什么作用呢?作用就是你了解了我們操作對象是——文件;同時了解對文件進(jìn)行的操作——數(shù)據(jù)的輸入及輸出;
那么,我們操作文件的一般思路是什么?思考1分鐘鐘再往下看!
操作一個文件時無非就以下三個步驟:
第一:打開文件;
第二:操作文件;
第三:關(guān)閉文件;
就是這么簡單,你在之前的生活經(jīng)歷中早就掌握文件的操作思路了;問題在于,在Linux中,怎么打開、操作、關(guān)閉文件?答案是用對應(yīng)的函數(shù)操作,所以IO的學(xué)習(xí)除了了解基本概念外,就是學(xué)習(xí)函數(shù)的的使用。
我先以標(biāo)準(zhǔn)IO 為例:我們通過四個函數(shù)來解析基本的操作思路;
標(biāo)準(zhǔn)IO中打開文件用 fopen()函數(shù);原型為 FILE *fopen(const char *path, const char *mode);從原型中可以看出,fopen()有兩參數(shù);形參const char *path對應(yīng)就是我需要打開的文件名稱,包括文件的路徑名稱;const char *mode指的是打開文件后我們要對文件進(jìn)行項什么樣的操作? 是讀、寫、還是添加的寫?參數(shù)如下:
mode 的參數(shù)有一些固定值;
r ——只讀方式打開,
r+ ——讀寫方式打開,
以上兩個參數(shù)必須要求文件存在;
w ——只寫方式打開,
w+ ——讀寫方式打來;
使用以上兩個參數(shù)時;若文件存在,則會清空文件,再寫入具體數(shù)據(jù)!若文件不存在,則創(chuàng)建文件再寫入數(shù)據(jù);
a —— 以只寫方式打開;
a+ —— 以讀寫方式打開;
以上兩個參數(shù)使用時,若文件存在,則在后面添加數(shù)據(jù),若文件不存在,則創(chuàng)建再寫入數(shù)據(jù);
上面的6個參數(shù)就是mode 可以寫入的全部值;(都是單獨使用的)
在fopen前有一個FILE *; 它是什么呢?當(dāng)我們創(chuàng)建一個打開一個文件時,就會創(chuàng)建一個FILE 結(jié)構(gòu)體描述改文件,或者說是創(chuàng)建一個FILE文件結(jié)構(gòu)體和實際的文件關(guān)聯(lián)起來;之后對FILE * 變量的操作就是對文件的操作;FILE 結(jié)構(gòu)體也稱為流;
標(biāo)準(zhǔn)IO關(guān)閉文件的函數(shù)是 fclose()函數(shù),原型為:int fclose(FILE *fp);
只要把對應(yīng)的文件流變量傳給fclose()就可以了;
我們先來看一個fopen()函數(shù)的例子;
#include
int main(int argc,char *argv[])
{
FILE *fp;
if(argc !=2)
{
printf("usage %s \n",argv[0]);
exit(1);
}
fp = fopen(argv[1],"w");
if(fp == NULL)
{
perror("perror");
exit(1);
}
fclose(fp);
return 0;
}
上面就是一個最簡單的打開文件的程序;
接下來要做的事就是怎么去操作文件?
文件的操作分兩種方式,對文件進(jìn)行讀,或者對文件進(jìn)行寫!
讀寫的函數(shù)比較多,作者以fgets()和fputs()為例來講解如何對文件進(jìn)行讀寫操作;首先是fgets(); 它的主要作用是從文件流中讀取數(shù)據(jù),原型: char *fgets(char *s, int size, FILE *stream);對應(yīng)的參數(shù)從后往前看,F(xiàn)ILE *stream 指的是要讀取的文件流,也會是要從此文件中讀取數(shù)據(jù);每次讀的大小對應(yīng) int size ,并把數(shù)據(jù)存放到 char *s 對應(yīng)的地址,成功會返回讀到的字節(jié)數(shù), 失敗返回NULL;
下面時fgets()的實例程序:
#include
#include
int main(int argc, char *argv[])
{
FILE *fp;
char buf[20];
if(argc !=2)
{
printf("usage %s \n",argv[0]);
exit(1);
}
fp = fopen(argv[1],"r");
if(fp == NULL)
{
perror("fopen failed");
exit(1);
}
while (fgets(buf, 20, fp) !=NULL)
{
printf("%s",buf);
}
fclose(fp);
return 0;
}
上面的程序中關(guān)于fgets()使用, 程序每次從fp對應(yīng)的文件中讀取19個字節(jié)數(shù)據(jù)并存在在buf中,并且在屏幕上打印出來;直到數(shù)據(jù)讀完為止;
那么,如果想從一個文件中讀取數(shù)據(jù)并寫到另一個文件中,該怎么做?這就可以在上面的程序基礎(chǔ)上添加一個函數(shù)的fputs();它的原型:int fputs(const char *s, FILE *stream); 對應(yīng)的參數(shù)FILE *stream 是被寫入的文件,也就是把數(shù)據(jù)寫入此文件中;const char *s 是需要寫入的數(shù)據(jù); 實現(xiàn)從一個文件中讀取數(shù)據(jù)并寫到另一個文件中的程序就可以這樣做;
#include
#include
int main(int argc,char *argv[])
{
FILE *read_fp,*write_fp;
char buf[10];
if(argc !=3)
{
printf("usage %s \n",argv[0]);
exit(1);
}
read_fp = fopen(argv[1],"r");
if(read_fp == NULL)
{
perror("read_fopen failed");
exit(1);
}
write_fp = fopen(argv[2],"w");
if(write_fp == NULL)
{
perror("write_fp fopen failed");
exit(1);
}
while(fgets(buf, 10, read_fp) !=NULL)
{
fputs(buf, write_fp);
}
fclose(read_fp);
fclose(write_fp);
return 0;
}
通過上面的概念及函數(shù)的使用,我們解析了標(biāo)準(zhǔn)IO中對文件的基本操作,當(dāng)然,對文件的操作函數(shù)還有很多,但操作思路基本一樣;讀者可以以此為突破口進(jìn)行更深入的學(xué)習(xí)。
- 贊