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