1. 程式人生 > >C語言檔案操作函式總結——超詳細

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(&currentTime);
    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 
版權宣告:本文為博主原創文章,轉載請附上博文連結!