c語言文件操作詳細

文件操作有多種形式首先解釋文本文件操作
當操作的文件時文本文件時,會將數據轉換爲ascii字符的值存放到文件中,在使用時在轉換會原來的值。這裏和printf函數的執行過程很相似
所以在講解文件之前先講解兩個相關函數
1.
//int printf(const char *_Format,…) 參數中的…是可變參
比如
int a=10;
printf(“a=%d\n”,a);
在執行時printf函數會開闢一個臨時空間,來存放printf函數中的雙引號中的字符,並且以ascii值的方式存放,並且10在函數中存放時會將其分爲1和0,然後通過itoa函數轉換爲ascii,所以當我們在屏幕上看到的值是,那些都是一個個字符所組成的內容。
並且,printf函數是有返回值的,他的返回值是int類型用於計算“”之間字符的個數。

2
int sprintf( char *str,const char * format,…);
sprintf()會根據參數format字符串來轉換並格式化數據, 然後將結果複製到參數str所指的字符串數組, 直到出現字符串結束(’\0’)爲止。關於參數format字符串的格式請參考printf()。
成功則返回參數str字符串長度, 失敗則返回-1, 錯誤原因存於errno中。
所以sprintf函數的作用和printf函數有一些類似,但是他不輸出,他只是將“ ”之間的字符串轉換爲單個字符包括空格,存入sprintf函數指定的數組中,存儲是以ascii方式存放的

3
記住關鍵是在理解寫入和讀取時我們需要站在程序的角度來看待,寫入就是將程序數據存放到文件中,讀取就是將文件內容讀入程序中,文件開闢時一般開闢4k大小的磁盤空間(這和文件磁盤格式有關),如果不夠則會在磁盤中在開闢一個空間,但是電腦顯示時是隻有一個文件的

FILE * fopen(const char * path,const char * mode);
表頭文件:
#include<stdio.h>
說明:
參數path字符串包含欲打開的文件路徑及文件名, 參數mode字符串則代表着流形態。
mode有下列幾種形態字符串:
r 打開只讀文件, 該文件必須存在。
r+ 打開可讀寫的文件, 該文件必須存在。
w 打開只寫文件, 若文件存在則文件長度清爲0, 即該文件內容會消失。若文件不存在則建立該文件。
w+ 打開可讀寫文件, 若文件存在則文件長度清爲零, 即該文件內容會消失。若文件不存在則建立該文件。
a 以附加的方式打開只寫文件。若文件不存在, 則會建立該文件, 如果文件存在, 寫入的數據會被加到文件尾, 即文件原先的內容會被保留。
a+ 以附加方式打開可讀寫的文件。若文件不存在, 則會建立該文件, 如果文件存在, 寫入的數據會被加到文件尾後, 即文件原先的內容會被保留。
上述的形態字符串都可以再加一個b字符, 如rb、w+b或ab+等組合, **加入b 字符用來告訴函數庫打開的文件爲二進制文件, 而非純文字文件。**不過在POSIX系統, 包含Linux都會忽略該字符。由fopen()所建立的新文件會具有
rb+打開一個用於讀寫的二進制文件
wb+創建一個用於讀寫的二進制文件
ab+打開一個用於讀寫的二進制文件

文件順利打開後, 指向該流的文件指針就會被返回。若果文件打開失敗則返回NULL, 並把錯誤代碼存在errno 中。

但是要注意的時r操作(不管有沒有w或者+)都不能用於創建一個新的文件,當文件存在時返回真,無則返回空指針

//FILE *fp=fopen("yhp.tx","w");//yhp.txt時相對路徑,在存放時是放在程序對應的文件中的
int ar[]={12,23,34,45,56};
FILE *fp=fopen("C:text//yhp.tx","w");//這就是絕對路徑,文件存放在指定的地方
if(NULL==fp)//文本文件存放的都ascii值
return -1;
for(int i=-;i<10;i++)
{
fprintf(fp,"%d ",ar[i];
}
fclose(fp);
fp=NULL;

下面是二進制文件的寫入操作,二進制文件操作的區別在於,二進制文件在存放數據是不會將數據轉換爲ascii的值存放而是內存中是什麼樣的,二進制文件就是如何存放的

//FILE *fp=fopen("yhp.tx","wb");//yhp.txt時相對路徑,在存放時是放在程序對應的文件中的
int ar[]={12,23,34,45,56};
int n=sizeof(ar)/sizeof(ar[0]);
FILE *fp=fopen("C:text//yhp.dat","wb");//這就是絕對路徑,文件存放在指定的地方
if(NULL==fp)//文本文件存放的都ascii值
return -1;
fwrite(ar,sizeof(int),n,fp);//這是一個專門處理二進制文件寫入的函數,但是有要求是,寫入目標必須是連續的
fclose(fp);
fp=NULL;

另外,值創建文件時,文件名的後綴時無所謂的,因爲我們使用文件時不會單獨將文件打開而是使用程序打開,但是比如我們文件的創建時是以二進制操作的,但是我們將其命名爲。txt文件,那麼在打開文件是會將二進制寫入的16進制數當做ascii的值然後表現而ascii字符

然後進行文本文件的讀取操作

int br[5];
FILE *fp=fopen("C:text//yhp.txt","r");//這就是絕對路徑,文件存放在指定的地方
if(NULL==fp)//文本文件存放的都ascii值
return -1;
for(int i=-;i<10;i++)
{
fscanf(fp,"%d ",br[i];
}
fclose(fp);
fp=NULL;

但是在使用fsacnf是需要記住fprintf輸入時雙引號%d後面的間隔是用是麼來間隔的,如果符後錯誤,那麼在讀取是就會出現錯誤,所以在讀取是我們一般使用fgetc函數,fgetc函數在讀取時時一個個字符進行讀取如果文本文件中需要存放的數據本身就是文本(也就是字符和字符串)時,他是不會進行itoa轉換的,而實直接將字符的ascii的值存放,所以在存放文本數據時,使用文本文件進行存放較爲方便

#include<windows.h>
int br[5];
FILE *fp=fopen("C:text//yhp.txt","r");//這就是絕對路徑,文件存放在指定的地方
if(NULL==fp)//文本文件存放的都ascii值
return -1;
char ch;
while(!feof(fp))//判斷文件是否讀到末尾,如果未讀到末尾,則返回假,然後求反
{
ch=fgetc(fp);//在讀取文件(使用時fgetc),存在一個文件定位指針(下標),會在文件操作中每讀取一個字節字符。該下標就會向後移動一個字節
cout<<ch;
Sleep(100);//<windows.h>文件中包含的睡眠函數,可以讓程序進行延緩100ms
}
fclose(fp);
fp=NULL;

上面的程序我們發現ch爲char類型,那麼在讀取時我們需要一個個字符的讀取,那麼速率就較爲緩慢,所以爲了應對這種問題我們採取下面的操作

#include<windows.h>
FILE *fp=fopen("C:text//yhp.txt","r");//這就是絕對路徑,文件存放在指定的地方
const int n=10;
if(NULL==fp)//文本文件存放的都ascii值
return -1;
char buff[n];//用於存放讀取的數據
while(!feof(fp))//判斷文件是否讀到末尾,如果未讀到末尾,則返回假,然後求反
{
fets(buff,n,fp);//給buff這個字符串了十個空間但實際它之存放9個數據,
printf("%s",buff);
Sleep(100);//<windows.h>文件中包含的睡眠函數,可以讓程序進行延緩100ms
}
fclose(fp);
fp=NULL;

fgets函數在執行時,因爲buff這個字符串的空間爲10所以在fgets讀取九個字符時,會在第十個空間賦值一個0(也就是\0)字符串的終止符,還有另一個情況就是在讀取文件時buff這個字符串存放九個字符,而某一行有13個字符那麼在第二次讀取時就會用新4個字符來替換前四個字符,當讀取時碰到換行字符(ascii值爲10,\n)就會在下一個空間賦值\0,使該字符串終止,應爲在printf函數讀取%s時,是根據\0來終止讀取數據的,下面我附上調試截圖,這是第一次buff讀取數據
在這裏插入圖片描述這是第二次讀取數據在這裏插入圖片描述
我們可以看到,當第二次讀取是碰見了\n符號,所以選擇了在第九個位置賦值了\0,然後第三次又繼續讀取
在這裏插入圖片描述
另外需要知道的是buff的空間是循環利用的,所以當fgets函數在第二次讀取時發現第八個空間的位置是\n,所以在第九個空間賦值爲\0,如果第五個空間是\n,則在第六個空間賦值爲\0,而第六個之後的空間內容是上一次讀取的內容沒有被覆蓋

**在這裏我要着重說明一個東西,我們平時使用回車鍵是,其實是使用了兩個功能,一個是\r回車符,它是將光標移動到這一行的首位另一個是\n換行,在使用

fgets和fgetc時都不會在讀取\r回車符,但是回車符的函數最用依舊存在,因爲在讀取時我們需要\r符來使光標回到行首

**

在讀取數據時,存放的數據類型是什麼樣子的,在讀取是類型就是那麼樣子,比如存放的時int類型那麼在讀取是我們不能把他讀取爲double類型,因爲不同類型的數據所佔用的內存大小是不同的,double的識別能力時8字節,而int的識別能力時4字節,如果在讀去時會出現識別範圍錯誤,當第一個識別錯誤時會造成連續效應,導致後面的數據讀取都會出現錯誤,而不僅僅時一個類型轉換的誤差

下面我們來寫另一個函數,函數目的是將一個文件的內容寫入到另一個文件中

#include<windows.h>
void main()
{
FILE *rfp=fopen("C:text//yhp.txt","r");//這就是絕對路徑,文件存放在指定的地方
FILE *wfp=fopen("C:text//llj.txt","w");
const int n=10;
if(NULL==fp)//文本文件存放的都ascii值
return -1;
char buff[n];//用於存放讀取的數據
while(!feof(fp))//判斷文件是否讀到末尾,如果未讀到末尾,則返回假,然後求反
{
fets(buff,n,rfp);//給buff這個字符串了十個空間但實際它之存放9個數據
fputs(buff,wfp);//fputs不需要指定buff的大小是因爲在讀取時函數會根據\0來判斷是否終止,所以不需要給定大小
Sleep(100);//<windows.h>文件中包含的睡眠函數,可以讓程序進行延緩100ms
}
fclose(fp);
fp=NULL;
}

在上面的函數很好理解,但是有一個地方需要我們注意,fputs函數在寫入時,雖然fgets函數在傳值時不會傳\r回車符,但是在寫入時放fputs函數在遇見\n換行符時,會自動加上一個\r回車符這就讓程序的讀取寫入時不會缺少內容

int main(int argc,char argv[],char envp)
首先這三個參數都存放在數據區
argc表示有多少個命令行參數,第一個就是執行程序名,所以argc最少爲1。
argv指向一個指針數組的首元素,數組中每個元素都是 char * 指針,指向整個命令行參數字符串。
envp[]環境參數,envp[],這個數組與剛纔的argv[]有些相似,它的最後一個元素也儲存的空指針

需要了解的函數,getc,getch,getchar

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章