第五天2017/04/06(上午:文件的“读写操作”)
生活随笔
收集整理的這篇文章主要介紹了
第五天2017/04/06(上午:文件的“读写操作”)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文件的“讀”、“寫”的理解不是站在“程序”的角度,而是站在“文件”的角度讀:從文件中讀取數據,輸出到程序中寫:從程序中讀取數據,寫入到文件中(1)在C程序中系統對文件進行的各種操作是通過指向文件結構體的指針變量實現的。定義指向文件結構歐體類型的指針變量的形式:FILE* 指針變量名;例如: FILE *fp1 , *fp2;
(2)文件的打開C語言文件的打開是通過stdio.h函數庫的fopen()函數實現的。fopen()函數的原型是:FILE* fopen(char *filename,char *mode);其中:filename是要打開的文件的文件名,mode是說明處理文件的方式。打開文件的調用方式是:文件指針變量=fopen(文件名,處理文件方式);例如: fopen(“a:\\exam1.c”,”r”)【如果文件不存在,造成打開文件失敗】FILE *pf = fopen("a:\\exam1.c","r");if(pf==NULL) //如果返回值是NULL,則表示文件不存在,打開文件失敗{cout<<"文件不存在,打開文件失敗"<<endl;exit(-1); //exit(0)表示正常退出,exit(非0)表示程序出錯后退出}
(3)文件的讀寫操作(當文件打開后,最常見的操作就是對文件的讀取和寫入操作)
下面介紹四種常用的文件的讀取和寫入操作的函數從文件讀取 | 向文件寫入①按 字符 讀寫的函數: fgetc() | fputc() 讀寫“一個”字符②按 字符串讀寫的函數: fgets() | fputs()③按格式要求讀寫的函數: fprintf() | fscanf()④按 數據塊讀寫的函數: fread() | fwrite()
上面常見的四種函數功能介紹以及應用舉例
①fgetc() | fputc()
調用形式:fgetc(文件型指針類型) 例:char ch = fgetc(fp);//作用:從一個文件中讀取一個字符//返回值:返回所讀取的一個字節。如果讀到文件末尾或者讀取出錯時返回EOF。
調用形式:fputc(字符,文件型指針類型); 例:fputc('A',fp);//執行過程:將字符‘A’(也可以是字符型變量)寫入文件的當前位置,并且使指向文件當前位置的指針下移一個字節。//返回值:如果寫入成功,返回的是該字符的ASCII值; 如果寫入失敗,返回EOF
②fgets() | fputs()
調用形式:char* fgets(字符數組,字符數,文件型指針變量); char *fgets(char *buf, int bufsize, FILE *stream);//作用:從fp指向的文件的當前位置讀取n-1個字符,再加上字符串結束標記'\0'(注意:字符串的結束標志‘\0’不寫入文件中去),一起放入字符數組中。
特殊情況:fgets函數一旦遇到字符'\n',就會在'\n'后面加上字符串結束字符'\0',然后把之前讀入包括'\n'和'\0'的字符數組存放到buf中//返回值:函數成功將返回字符數組的首地址; 失敗或讀到文件結尾返回NULL。
//【分析】如果開辟的buf過大,則不會出現任何問題,但是會浪費內存空間;但是如果開辟的buf過小,會導致。見下面例子:
假設文件中有下面兩行字符串:
Love,I Have
Since you can do it.
//先用fgets(str1,6,file1);去讀取,則讀取后 str1 = “Love,\0”
//再執行fgets(str1,20,file1);去讀取:此時從I開始讀取,讀取19個字節,但是由于提前遇到'\n'字符,會在'\n'后面加上'\0',因此讀取后結果str1 = " I Have\n"
因此我們不能直接通過fgets的返回值來判斷函數是否是出錯而終止的,應該借助feof函數或者ferror函數來判斷。調用形式:int fputs(const char* str,FILE* fpout);【使用實例1】
#include <stdio.h>
#define LENGTH 100
int main(void)
{ FILE *fd; char str[LENGTH]; //創建一個文件 fd = fopen("hello.txt","w+"); //往文件里面寫入字符串“"hello.world" if(fd) { fputs("hello,world",fd); } //關閉文件 fclose(fd); //再次打開文件,并讀出所有字符串 fopen("hello.txt","r"); fgets(str,LENGTH,fd); //輸出到標準輸出設備 printf("%s\n",str); //關閉文件 fclose(fd);
}
【使用實例2】 將文件d:\data1.txt中的內容復制到d:\data2.txt中。
{FILE *f_in, *f_out; char str[50];f_out = fopen(“d:\\data1.txt”,"r"); //讀取f_in = fopen(“d:\\data2.txt”,"w"); //寫入…… …… ……while(!feof(f_out)) //如果f_out遇到的不是字符串結束標志,則進入while循環{fgets(str,30,f_out); //f_out讀取30個字符賦值給strfputs(str,f_in); //把str寫入到f_in打開的文件中}fclose(f_out); fclose(f_in);
}
③fprintf() | fscanf()
調用形式:int fprintf(文件型指針變量, 格式控制, 輸出表列);
//解釋:函數fprintf()的作用與printf()相類似,只是輸出對象不是“標準輸出設備”而是“文件”,即按照格式要求“將數據寫入文件”。
例如: fprintf(fp,"%ld,%s,%5.1f",num,name,score);//作用:將變量num、name、score按照%ld、%s、%5.1f的格式寫入fp指向的文件的當前位置調用形式:int fscanf(FILE* stream, const char* format, [argument...]);翻譯成int fscanf(文件型指針變量, 格式控制, 輸出表列);例: /*從文件中讀取數據*/fscanf(stream,"%s",s);fscanf(stream,"%ld",&l); //和scanf對比相類似,輸出表列的變量加上 &fscanf(stream,"%f",&fp);fscanf(stream,"%c",&c);④按數據塊讀寫的函數fread()、fwrite()
調用形式:size_t fread( void *buffer, size_t size, size_t count, FILE *stream) ;
buffer buffer是一個變量,它用于存放從stream中讀取到的數據.
size 要讀的每個數據項的字節數,單位是字節byte.
count 要讀count個數據項,每個數據項size個字節.
stream 輸入流.
//作用:作用是從文件中讀出成批的數據塊。即:fread是一個函數。從一個文件流中讀數據,最多讀取//count個項,每個項size個字節,如果調用成功返回實際讀取到的項個數(小于或等于count),如果不成功或讀到文件末尾返回 0。
//返回值:如果函數fread()操作成功,則返回值為實際從文件中讀取數據塊的個數。調用形式:fwrite(寫入文件的數據塊的“存放地址”,一個數據塊所占的字節數,數據塊的個數,文件型指針變量);size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);//返回值是:寫入數據塊的個數(次數),因此由返回值可以判斷是否讀取到值!,見下面示例:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct stu
{int age;char ch[100];
}st[3]={{20,"Tom"},{21,"Mary"},{23,"Faker"}};int main()
{FILE *fp = fopen("D.txt","w+");if(!fp){printf("打開失敗\n");exit(-1);}//方式一://while(fwrite(&st[0],sizeof(struct stu),3,fp) != 3)//{//}int count = fwrite(&st[0],sizeof(struct stu), 3,fp); //正確,因為st[]數組的大小就是3.//int count = fwrite(&st[0],sizeof(struct stu),300,fp); //錯誤,從st[]數組中讀取數據時,會發生越界//方式二:讀結構體數組時最好用方式二,逐個讀取st[i]//for(int i=0;i<3;i++)//{// if(fwrite(&st[i],sizeof(struct stu),1,fp) !=1 ) //第三個參數是1,表示一次讀取一個st[i]// {// printf("寫入失敗,退出程序\n");// exit(-1);// }//}return 0;
}buffer:是一個指針,與fread(“存取數據的地址”)中不同,對fwrite來說,是要 “獲取數據的地址”,例如buffer中存放著很多數據,把buffer中的數據寫到stream打開的文件夾中。
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct stu
{int age;char ch[100];
}st[3];int main()
{//為了驗證上面fwrite是否把結構體數組中存放的數據寫入到文件C.txt中去,///我們可以用下面的程序進行測試:用一個文件指針fp以“r”的方式打開文件,///把讀取到的數據存放到&st[i]中,然后把是st[i]中的數據輸出,看下///輸出結果是不是上面fwrite寫入的數據?如果是,表明寫入成功;如果不是,///表明寫入失敗。FILE *fp = fopen("C.txt","r+");if(!fp){printf("打開失敗\n");exit(-1);}方式一:// if(fread(&st[0],sizeof(struct stu),3,fp) !=3 ) //第三個參數是3,一次讀取3個st[i]// {// printf("寫入失敗,退出程序\n");// exit(-1);// }// for(int i=0;i<3;i++)// {// printf("%5d,%s\n",st[i].age,st[i].ch);// }//方式二 for(int i=0;i<3;i++){if(fread(&st[i],sizeof(struct stu),1,fp) !=1 ){printf("寫入失敗,退出程序\n");exit(-1);}printf("%5d,%s\n",st[i].age,st[i].ch);}return 0;
}
【fread簡單示例】
例如:已知stu1是一個結構體struct student變量,則
fread(&stu1, sizeof(struct student ), 1, fp);
表示的含義是從文件類型指針fp指向的文件的當前位置開始,讀取1個數據塊,該數
據塊為結構體struct student類型變量所占字節數,然后將讀取的內容放入變量stu1中。
【fwrite簡單示例】例如:已知struct student 類型的數組stu[20],則語句fwrite(&stu[1], sizeof(struct student ), 2, fp);
表示的含義是 ——> 從結構體數組元素stu[1]存放的地址開始,以一個結構體struct student類型變量所占字節數為一個數據塊,共寫入文件類型指針fp指向的文件2個數據塊,即stu[1]、stu[2]的內容寫入文件。如果操作成功,函數的返回值為2。【fread、fwrite綜合示例1】創建一個文件并寫入一段數據,然后讀取出來。
#include <stdio.h>void main( void )
{FILE *stream;char list[30];int i, numread, numwritten;// 以文本方式打開文件if( (stream = fopen( "fread.out", "w+t" )) != NULL ) // 如果讀取無誤{for ( i = 0; i < 25; i++ ) //給list[i]數組的每個元素進行賦值list[i] = (char)('z' - i);//fwrite:從list數組中獲取字符,要寫入大小為sizeof(char)的字符,一共寫入25次,寫到stream打開的文件中,返回值是實際寫入的次數numwritten = fwrite( list, sizeof( char ), 25, stream );printf( "Wrote %d items\n", numwritten );fclose( stream );}else{printf( "Problem opening the file\n" );}if( (stream = fopen( "fread.out", "r+t" )) != NULL ) // 文件讀取{numread = fread( list, sizeof( char ), 25, stream );printf( "Number of items read = %d\n", numread );printf( "Contents of buffer = %.25s\n", list );fclose( stream );}else{printf( "File could not be opened\n" );}
}
運行結果:Wrote 25 itemsNumber of items read =25Contents of buffer = zyxwvutsrqponmlkjihgfedcb【fread、fwrite綜合示例2】將10個學生記錄輸入文件d:\stu中,然后顯示。
struct ST
{char class[6];…………
}a[N],stu; //定義一個結構體數組a[N]和結構體變量stuint main()
{int i; FILE *fp = fopen("d:\\stu","wb"); //寫入方式打開文件夾for(i=0;i<N;i++) //給結構體數組a[N]中的每個元素輸入數據{printf("\n\t請輸入班級:"); scanf("%s",a[i].class);…… …… …… }if(fwrite(a,sizeof(struct ST),N,fp)!=N) //用fwrite函數寫入往fp打開的文件中寫入大小為sizeof(struct ST),個數為N的數據{//如果fwrite返回的值不等于Nprintf("文件不能寫入數據.\n");//那么,打印這句話 exit(1); //異常退出}fclose(fp);//關閉fp打開的文件夾,此時fp已經不指向之前打開的文件夾fp=fopen("d:\\stu","rb"); //以讀取方式打開 “上面剛寫入數據的文件夾d:\\stu” for(i=0;i<N;i++){ if(fread(&stu,sizeof(struct ST),1,fp)= =1) //從fp打開的文件讀取1個以stu的地址為起始地址,大小為sizeof(struct ST),個數為1的數據,存放到&stu中去printf("\t%6s%10ld%9s%5d%6d%8d\n",stu.class,… … … );//printf在屏幕上格式化輸出else //如果返回值不是1{printf("文件不能讀取數據.\n"); exit(1); //則異常退出}}fclose(fp);
}(4)文件的關閉(當文件操作結束后,為了防止誤操作等操作破壞打開的文件,應該在使用后及時的關閉)具體做法:fclose(文件指針fp); //則將fp指向的文件關閉,fp不在指向之前被打開的文件【拓展】文件中常用的函數 fseek()、feof()、rewind()、ftell()fseek():int fseek(FILE *stream, long offset, int fromwhere);等價于fseek(文件型指針變量,偏移量,起始位置);
/*int fseek( FILE *stream, long offset, int origin);
第一個參數stream為文件指針
第二個參數offset為偏移量,正數表示正向偏移,負數表示負向偏移第三個參數origin設定從文件的哪里開始偏移,可能取值為: SEEK_SET、SEEK_CUR、 SEEK_END
SEEK_SET: 文件開頭
SEEK_CUR: 當前位置
SEEK_END: 文件結尾
其中SEEK_SET,SEEK_CUR和SEEK_END依次為0,1和2.
簡言之:
fseek(fp,100L,0);把stream指針移動到離文件開頭100字節處;
fseek(fp,100L,1);把stream指針移動到離文件當前位置100字節處;
fseek(fp,-100L,2);把stream指針退回到離文件結尾100字節處。
*/
函數設置文件指針stream的位置:如果執行成功,stream將指向以fromwhere為基準,偏移offset(指針偏移量)個字節的位置,函數返回0。如果執行失敗(比如offset超過文件自身大小),則不改變stream指向的位置,函數返回一個非0值。feof():用來檢測一個指向文件的指針是否已經指到了文件最后的結束標志EOF。調用的一般形式為: feof(文件型指針變量);如果文件型指針指向的文件的當前位置為結束標志EOF,則函數返回一個非零值,否則返回0值。
rewind():將令指向文件的指針重新指向文件的開始位置。函數無返回值。其調用形式為: rewind(文件型指針變量);例如: rewind(fp);//fp是一個指向文件的指針,執行該語句后,fp指向文件的開始位置,即文件的第一個數據。
ftell():用于測試指向文件的指針的當前位置。調用方式為: ftell(文件型指針變量);//函數的返回值是一個常整型數,如果測試成功,則返回指向文件的指針當前指向的位置距離文件開頭的字節數,否則返回-1L #include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main()
{//按字符FILE *fp = fopen("A.txt","a+"); //a+表示追加char ch[] = "ABCDDCBA";int i=0;while(ch[i]!='\0'){if(fputc(ch[i],fp)==0){printf("func:fput error");exit(-1);}i++;}fclose(fp);getchar();
}
int main()
{//按行FILE *fp = NULL;char *filename = "code.txt"; if((fp = fopen(filename,"r"))==NULL) //“r”打開文件{printf("func:fopen() err\n");return 0;}char ch[300];memset(ch,0,sizeof(char)*300);
//從fp打開的文件中讀取數據,顯示到窗口中有以下兩種方式
//方式一//while(fgets(ch,300,fp)) //逐行讀取fp打開的文件,把讀到的數據存放到ch[]中//{// printf("%s\n",ch);//注意:此時自己加上字符 '\n'// memset(ch,0,sizeof(char)*300);//}
//方式二:(這種方式比方式一好!)while(!feof(fp)) //此處是!feof(fp),不要忘記感嘆號'!'{fgets(ch,300,fp); //逐行讀取fp打開的文件,把讀到的數據存放到ch[]中printf("%s\n",ch);memset(ch,0,sizeof(char)*300);}fclose(fp);getchar();
}【總結】文件操作
1、C語言文件讀寫概念建立以及文件讀寫API的熟悉
API的種類
一、文件讀寫APIfgetc fgetc 按照字符讀寫文件fputs fgets 按照行讀寫文件(讀寫配置文件)fread fwrite 按照塊讀寫文件(大數據塊遷移)fprintf fscanf 按照格式化讀寫文件二、文件控制API文件是否結束文件指針的定位、跳轉
三、用API做項目
2、項目開發,配置文件讀寫庫的設計與實現
3、項目開發:大數據文件加密解密設計與實現
總結
以上是生活随笔為你收集整理的第五天2017/04/06(上午:文件的“读写操作”)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第四天2017/03/31(下午2:结构
- 下一篇: 第五天2017/04/06(下午1:C、