C語言檔案操作函式總結——超詳細
版權宣告
本文原創作者:谷哥的小弟
作者部落格地址:http://blog.csdn.net/lfdfhl
檔案與流
在C語言中有三種標準流:
stdin(standard input stream)標準輸入流。在大多數環境中為從鍵盤輸入;scanf( )和getchar( )等函式會從該流中讀取字元
stdout(standard output stream)標準輸出流。在大多數環境中為輸出至顯示器介面。printf( )、puts( )、putchar( )等函式會向該流中寫入字元。
stderr(standard error stream)標準錯誤流。在大多數環境中為輸出至顯示器介面。
在C語言中用FILE表示檔案型別並提供相應的操作。FILE定義在<stdio.h>標頭檔案中,其具體實現方法因編譯器而異,一般以結構體的形式實現。表示標準流的stdin、stdout、stderr都是指向FILE的指標。
檔案常見操作
接下來介紹常見的檔案操作。
1、開啟檔案
利用fopen( )開啟檔案,函式如下:
FILE *fopen( const char *filename, const char *mode );
第一個引數:該引數為字串型別,表示要開啟的檔案的名稱
第二個引數:該引數為字串型別,表示開啟模式(只讀、只寫、更新、追加)
fopen( )函式會為要開啟的檔案建立流並返回一個指向檔案物件的FILE*型指標。
2、關閉檔案
利用fclose( )開啟檔案,函式如下:
int fclose( FILE *stream );
輸入引數:要關閉的檔案的指標
返回值:成功關閉返回0,否則返回EOF
練習:檔案的開啟與關閉
程式碼如下:
#include <stdio.h> #include <stdlib.h> int main() { FILE *fp=fopen("D:\\test.txt","r"); if(fp==NULL){ puts("檔案開啟失敗"); }else{ puts("成功開啟檔案"); } int result=fclose(fp); if(result==0){ puts("成功關閉檔案"); }else{ puts("檔案關閉失敗"); } return 0; }
結果如下:
成功開啟檔案
成功關閉檔案
3、從檔案中讀取資料
利用fscanf( )從檔案中讀取資料,函式如下:
int fscanf( FILE *stream, const char *format, ... );
與scanf( )函式比起來,fscanf( )函式多了一個輸入引數即FILE *stream;它表示從哪個檔案讀取資料。除此以外,它與scanf( )函式完全相同。例如,要從fp中讀取十進位制整數值並儲存是x,程式碼如下:
fscanf(fp,"%d",&x);
練習:從檔案讀取學生的成績並計算各科平均成績
在D盤根目錄下準備成績檔案score.txt
內容如下:
小明 70 84
小王 80 90
小坤 90 90
程式碼如下:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int number=0;
char name[20];
int chinese;
int math;
int chinese_sum=0;
int math_sum=0;
FILE *fp=fopen("D:\\score.txt","r");
if(fp!=NULL){
puts("開始讀取資料");
while(fscanf(fp,"%s%d%d",name,&chinese,&math)==3){
printf("%s %d %d\n",name,chinese,math);
number++;
chinese_sum=chinese_sum+chinese;
math_sum=math_sum+math;
}
puts("-------------");
printf("平均 %d %d\n",chinese_sum/number,math_sum/number);
}else{
puts("檔案開啟失敗");
}
int result=fclose(fp);
if(result==0){
puts("成功關閉檔案");
}else{
puts("檔案關閉失敗");
}
return 0;
}
核心程式碼就一行:
while(fscanf(fp,"%s%d%d",name,&chinese,&math)==3){ }
在此,利用fscanf( )函式讀取score.txt中的每一行資料並將學生名字存入變數name,語文成績存入chinese,數學成績存入math;fscanf( )函式的返回值為讀取到的資料個數。其餘的程式碼不再解釋,也可以參照之前關於scanf( )函式的介紹。
結果如下:
開始讀取資料
小明 70 84
小王 80 90
小坤 90 90
-------------
平均 80 88
成功關閉檔案
4、向檔案中寫入資料
利用fprintf( )向檔案中寫入資料,函式如下:
int fprintf( FILE *stream, const char *format, ... );
fprintf( )函式的使用也很簡單,與printf( )函式比起來它多了一個輸入引數即FILE *stream;它表示向哪個檔案寫入資料。除此以外,它與printf( )函式完全相同。例如,要向fp中寫入十進位制整數值,程式碼如下:
fprint(fp,"%d",x);
練習:向檔案中寫入當前時間
程式碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
FILE *fp;
time_t currentTime = time(NULL);
struct tm *timeStruct = localtime(¤tTime);
if ((fp = fopen("D:\\time.txt", "w"))!= NULL){
puts("將當前日期和時間儲存至檔案");
int year=timeStruct->tm_year + 1900;
int month=timeStruct->tm_mon + 1;
int day=timeStruct->tm_mday;
int hour=timeStruct->tm_hour;
int minute=timeStruct->tm_min;
int second=timeStruct->tm_sec;
fprintf(fp,"%d %d %d %d %d %d\n",year,month,day,hour,minute,second);
fclose(fp);
}
return 0;
}
要點概述:
include包含了與時間相關的標頭檔案<time.h>
利用time( )函式得到系統的日曆時間(Calendar Time)
利用localtime( )得到本地時間;該方法的返回值是struct tm型別的指標
從timeStruct中分別獲取年月日時分秒
利用fprintf( )將年月日時分秒儲存至檔案
5、scanf( )、fscanf( )、printf( )、fprintf( )小結
在本文開頭,我們提到:標準流的stdin、stdout、stderr都是指向FILE的指標。也就是說:這三者都可以直接傳遞給fscanf( )、fprintf( )函式的第一個引數。因此可知,以下兩組程式碼的功能是相同的。
scanf("%d",&x);
fscanf(stdin,"%d",&x);
printf("%d",x);
fprintf(stdout,"%d",x);
也就是說:
scanf( )是輸入源被限定為標準輸入流的fscanf( )
printf( )是輸出目標被限定為標準輸出流的fprintf( )
6、fgetc( )和fputc( )
之前我們利用putchar( )和getchar( )將鍵盤輸入的文字顯示到控制檯
程式碼如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ch;
while((ch=getchar())!=EOF){
putchar(ch);
}
return 0;
}
在該示例中是從鍵盤讀入資料,輸出到控制檯。
在此,介紹兩個非常類似的函式。
首先來看fgetc( ):
int fgetc( FILE *stream );
該函式用於從檔案中讀取一個字元並將其轉為int型作為函式的返回值。
接著來看fputc( ):
int fputc( int ch, FILE *stream );
該函式用於向檔案中寫入一個字元。
練習:將檔案內容顯示至控制檯
程式碼如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ch;
FILE *fp;
char fileName[FILENAME_MAX];
printf("請輸入檔案路徑:");
scanf("%s",fileName);
if((fp=fopen(fileName,"r"))==NULL){
puts("檔案開啟失敗");
}else{
while((ch=fgetc(fp))!=EOF){
putchar(ch);
}
fclose(fp);
}
return 0;
}
核心程式碼:
利用fgetc( )從檔案中讀取資料,利用putchar( )將資料顯示至控制檯
結果如下:
請輸入檔案路徑:d:\\score.txt
小明 70 84
小王 80 90
小坤 90 90
練習:檔案的複製
程式碼如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ch;
FILE *sfp;
FILE *dfp;
char sName[FILENAME_MAX];
char dName[FILENAME_MAX];
printf("請輸入原始檔路徑:");
scanf("%s",sName);
printf("請輸入目標檔案路徑:");
scanf("%s",dName);
if((sfp=fopen(sName,"r"))==NULL){
puts("原始檔開啟失敗");
}else{
if((dfp=fopen(dName,"w"))==NULL){
puts("目標檔案開啟失敗");
}else{
while((ch=fgetc(sfp))!=EOF){
fputc(ch,dfp);
}
fclose(dfp);
fclose(sfp);
}
}
return 0;
}
核心程式碼:
利用fgetc( )從原始檔sName中讀取資料,利用fputc( )將資料寫至目標檔案dName。假若dName不存在,則會先建立該檔案再進行檔案的拷貝;這點和Java中的FileOutputStream是非常類似的。
結果如下:
請輸入原始檔路徑:d:\\score.txt
請輸入目標檔案路徑:d:\\copy.txt
7、fgets( )和fputs( )
與fgetc( )和fputc( )類似,可採用fgets( )和fputs( )從檔案中讀出或者寫入字串。
先來看fputs( ):
int fputs( const char *str, FILE *stream );
將str指向的字串寫入stream指向的檔案流,成功返回非負數;反之EOF。請注意:該函式輸入完成後不會增加額外的特殊字元(如換行符等)
示例如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp = fopen("D:\\test.txt", "w");
fputs("hello c programming\n", fp);
fputs("hello c++ programming\n", fp);
fclose(fp);
puts("已將字串寫入檔案");
return 0;
}
結果如下:
已將字串寫入檔案
再來看fgets( ):
char *fgets( char *str, int count, FILE *stream );
該函式從檔案指標stream指向的檔案內讀取字串並儲存到指標str所指向的記憶體空間中,直至已讀size-1個字元或出現換行符或檔案末尾時為止;當讀取錯誤或者讀到檔案末尾EOF返回NULL。請注意:該函式會讀取最後的換行符’\n’
示例如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[300];
FILE *fp= fopen("D:\\test.txt", "r");
//讀取第一行的內容
char *strLine1=fgets(str, 200, fp);
printf("%s",strLine1);
//讀取第二行的內容
char *strLine2=fgets(str, 200, fp);
printf("%s",strLine2);
fclose(fp);
return 0;
}
結果如下:
hello c programming
hello c++ programming
剛才我們事先知道D:\test.txt檔案中有兩行文字,所以連續兩次呼叫fgets( )讀取資料。但是,很多時候我們事先是不可能知道的檔案的內容;所以,程式碼需要優化:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[300];
FILE *fp= fopen("D:\\test.txt", "r");
char *stringLine;
while((stringLine=fgets(str, 200, fp))!=NULL){
printf("%s",stringLine);
}
fclose(fp);
return 0;
}
8、fread( )和fwrite( )
雖然可使用函式 fprintf ( )和 fscanf( ) 從磁碟檔案中讀寫任何型別的檔案,但是效率並不高。所以,我們可採用fread( )和fwrite( )按照二進位制的形式對檔案進行讀寫操作。
原型如下:
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
int fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
兩個函式輸入引數的個數和型別一致,概述如下:
第一個引數:指向讀寫資料首地址的指標。
第二個引數:要操作的單個數據的大小。例如,int型資料的大小就是sizeof(int)
第三個引數:資料個數
第四個引數:檔案指標
練習:利用fread( )和fwrite( )讀寫基本型別資料
程式碼如下(寫):
#include <stdio.h>
#include <stdlib.h>
//利用fwrite()寫資料
int main()
{
FILE * fp;
int buffer[] = {9, 5, 2, 7};
if((fp = fopen ("D:\\number.txt", "wb"))!=NULL){
fwrite (buffer, sizeof(int), 4, fp);
fclose (fp);
}
puts("已將資料按照二進位制的形式存入檔案");
return 0;
}
結果如下(寫):
已將資料按照二進位制的形式存入檔案
程式碼如下(讀):
#include <stdio.h>
#include <stdlib.h>
//利用fread()讀資料
int main()
{
int i;
FILE * fp;
int buffer[4];
if((fp = fopen ("D:\\number.txt", "rb"))!=NULL){
fread(buffer, sizeof(int), 4, fp);
fclose (fp);
}
for(i=0;i<4;i++){
printf("%d ",buffer[i]);
}
return 0;
}
結果如下(讀):
9 5 2 7
練習:利用fread( )和fwrite( )讀寫結構體
程式碼如下(寫):
#include <stdio.h>
#include <stdlib.h>
//利用fwrite()寫資料
typedef struct{
int age;
char name[20];
}Student;
int main()
{
int i;
FILE * fp;
Student stu1={18,"zxx"};
Student stu2={19,"hmm"};
Student stu3={29,"lqn"};
Student studentArray[3]={stu1,stu2,stu3};
if((fp = fopen ("D:\\student.txt", "wb"))!=NULL){
for(i=0;i<3;i++){
fwrite(&studentArray[i],sizeof(Student),1,fp);
}
puts("已將結構體型別資料按照二進位制的形式存入檔案");
fclose (fp);
}
return 0;
}
結果如下(寫):
已將結構體型別資料按照二進位制的形式存入檔案
程式碼如下(讀):
#include <stdio.h>
#include <stdlib.h>
//利用fread()讀資料
typedef struct{
int age;
char name[20];
}Student;
int main()
{
FILE *fp;
Student stu;
if((fp = fopen ("D:\\student.txt", "rb"))!=NULL){
while((fread(&stu,sizeof(Student),1,fp))==1){
printf("%d %s\n",stu.age,stu.name);
}
fclose(fp);
}
return 0;
}
結果如下(讀):
18 zxx
19 hmm
29 lqn
9、fread( )和fwrite( )使用小結
開啟檔案的模式為“rb”或者“wb”表示按照二進位制讀或者按照二進位制寫
按照二進位制方式將資料存入硬碟中檔案,我們開啟該檔案後是無法讀懂的
每次讀或寫資料後指標都會指向下一個待寫或者待讀資料的位置
在利用fread( )和fwrite( )讀寫完資料後需呼叫fclose( )方法關閉流
---------------------
作者:谷哥的小弟
來源:CSDN
原文:https://blog.csdn.net/lfdfhl/article/details/83752060
版權宣告:本文為博主原創文章,轉載請附上博文連結!