C語言檔案操作之—-檔案的讀寫

來源:互聯網
上載者:User

當檔案按指定的工作方式開啟以後,就可以執行對檔案的讀和寫。下面按檔案的性質分類進行操作。針對文字檔和二進位檔案的不同性質,對文字檔來說,可按字元讀寫或按字串讀寫;對二進位檔案來說,可進行成塊的讀寫或格式化的讀寫。
1. 讀寫字元
    C提供fgetc和fputc函數對文字檔進行字元的讀寫,其函數的原型存於stdio.h標頭檔中,格式為:
    int fgetc(FILE *stream)
    fgetc( )函數從輸入資料流的當前位置返回一個字元,並將檔案指標指標移到下一個字元處,如果已到檔案尾,函數返回EOF,此時表示本次操作結束,若讀寫檔案完成,則應關閉檔案。
int fputc(int ch,FILE *stream)
fputc()函數完成將字元c h的值寫入所指定的流檔案的當前位置處,並將檔案指標後移一位。fputc()函數的傳回值是所寫入字元的值,出錯時返回EOF。

[例8-2] 將存放於磁碟的指定文字檔按讀寫字元方式逐個地從檔案讀出,然後再將其顯示到螢幕上。採用帶參數的main( ),指定的磁碟檔案名稱由命令列方式通過鍵盤給定。
#i nclude<stdio.h>
main(argc,argv)
int argc;
char *argv[];
{
    char ch;
    FILE *fp;
    int i;
    if((fp=fopen(argv[1],"r"))==NULL) /* 開啟一個由argv[1]所指的檔案*/
    {
        printf("not open");
        exit(0);
    }
    while ((ch=fgetc(fp))!=EOF) /* 從檔案讀一字元,顯示到螢幕*/
        putchar(ch);
    fclose(fp);
}
    程式是一帶參數的main( )函數,要求以命令列方式運行,其參數argc是用於記錄輸入參數的個數, argv是指標數組,用於存放輸入參數的字串,串的個數由argc描述。假設我們指定讀取的檔案名稱為L8-2.c,並且列表檔案內容就是來源程式。經過編 譯和串連產生可執行檔檔案L8-2.exe。運行程式l8-2.exe,輸入的命令列方式為:
c:/tc>l8-2 L8-2.c
    上述程式以命令列方式運行,其輸入參數字串有兩個,即argv[0]="c:/tc>l8-2"、argv[1]=" L8-2.c ",argc = 2。故開啟的檔案是L8-2.c 。程式中對fgetc( )函數的傳回值不斷進行測試,若讀到檔案尾部或讀檔案出錯,都將返回C的整型常量EOF,其值為非零有效整數。程式的運行輸出為來源程式本身:
c:/tc>l8-2 L8-2.c
#i nclude <stdio.h>
main( argc,argv)
int argc;
char *argv[];
{
    char ch;
    FILE *fp;
    int i;
    if((fp=fopen(argv[1],"r"))==NULL) /* 開啟一個由argv[1] 所指的檔案*/
    {
        printf("not open");
        exit(0);
    }
    while ((ch=fgetc(fp))!=EOF) /* 從檔案讀一字元,顯示到螢幕*/
        putchar(ch);
    fclose(fp);
}

[例8-3] 從鍵盤輸入字元,存到磁碟檔案test.txt中:
#i nclude <stdio.h>
main( )
{
    FILE fp; / *定義檔案變數指標* /
    char ch;
    if((fp=fopen("test.txt","w"))==NULL)  /*以唯寫方式開啟檔案*/
    {
        printf("cannot open file!/n");
        exit(0);
    }
    while ((ch=fgetchar())!='/n') /*只要輸入字元非斷行符號符* /
        fputc(ch,fp) /*寫入檔案一個字元*/
    fclose(fp);
}
    程式通過從鍵盤輸入一以斷行符號結束的字串,寫入指定的流檔案test.txt,檔案以文本唯寫方式開啟,所以流檔案具有可讀性,能支援各種字元處理工具訪問。簡單地說,我們可以通過DOS提供的type命令來列表顯示檔案內容。
運行程式:
I love china!
在DOS作業系統環境下,利用type 命令顯示test.txt檔案如下:
c:/tc> type test.txt
I love china!

2. 讀寫字串
    C提供讀寫字串的函數原型在stdio.h標頭檔中,其函數形式為:
    Char *fgets(char *str,int num,FILE *stream)
    fgets() 函數從流檔案stream中讀取至多num-1個字元,並把它們放入str指向的字元數組中。讀取字元直到遇見斷行符號符或E O F(檔案結束符)為止,或讀入了所限定的字元數。
    int fputs(char *str,FILE *stream)
    fputs( )函數將str指向的字串寫入流檔案。操作成功時,函數返回0值,失敗返回非零值。

[例8-4] 向磁碟寫入字串,並寫入文字檔test.txt:
#i nclude<stdio.h>
#i nclude<string.h>
main( )
{
    FILE *fp;
    char str[128];
    if ((fp=fopen("test.txt","w"))==NULL) /*開啟唯寫的文字檔*/
    {
        printf("cannot open file!");
        exit(0);
    }
    while((strlen(gets(str)))!=0)
    { /*若串長度為零,則結束*/
        fputs(str,fp); /*寫入串*/
        fputs("/n",fp); /*寫入斷行符號符*/
    }
    fclose(fp); /*關檔案*/
}
    運行該程式,從鍵盤輸入長度不超過1 2 7個字元的字串,寫入檔案。如串長為0,即空串,程式結束。
輸入:Hello!
How do you do
Good-bye!

運行結束後,我們利用dos的type命令列表檔案:
c:/tc>type test.txt
Hello!
How do you do
Good-bye!
這裡所輸入的空串,實際為一單獨的斷行符號符,其原因是gets函數判斷串的結束是以斷行符號作標誌的。

[例8-5] 從一個文字檔test1.txt中讀出字串,再寫入令一個檔案test2.txt。
#i nclude<stdio.h>
#i nclude<string.h>
main( )
{
    FILE *fp1,*fp2;
    char str[128];
    if ((fp1=fopen("test1.txt","r"))==NULL)
    { / * 以唯讀方式開啟檔案1 */
        printf("cannot open file/n");
        exit(0);
    }
    if((fp2=fopen("test2.txt","w"))==NULL)
    { /*以唯寫方式開啟檔案2 */
        printf("cannot open file/n");
        exit(0);
    }
    while ((strlen(fgets(str,128,fp1)))>0)
    /*從檔案中讀回的字串長度大於0 */
    {
        fputs(str,fp2 ); /* 從檔案1讀字串並寫入檔案2 */
        printf("%s",str); /*在螢幕顯示*/
    }
    fclose(fp1);
    fclose(fp2);
}
    程式共操作兩個檔案,需定義兩個檔案變數指標,因此在操作檔案以前,應將兩個檔案以需要的工作方式同時開啟(不分先後),讀寫完成後,再關閉檔案。設計過 程是按寫入檔案的同時顯示在螢幕上,故程式運行結束後,應看到增加了與原檔案相同的文字檔並顯示檔案內容在螢幕上。

3. 格式化的讀寫
    前面的程式設計中,我們介紹過利用scanf( )和printf( )函數從鍵盤格式化輸入及在顯示器上進行格式化輸出。對檔案的格式化讀寫就是在上述函數的前面加一個字母f成為fscanf( )和fprintf( )。其函數調用方式:
    int fscanf(FILE *stream,char *format,arg_list)
    int fprintf(FILE *stream,char *format,arg_list)
    其中,stream為流檔案指標,其餘兩個參數與scanf( )和printf( )用法完全相同。

[例8-6] 將一些格式化的資料寫入文字檔,再從該檔案中以格式化方法讀出顯示到屏
幕上,其格式化資料是兩個學生記錄,包括姓名、學號、兩科成績。
#i nclude<stdio.h>
main( )
{
    FILE *fp;
    int i;
    struct stu{ /*定義結構體類型*/
        char name[15];
        char num[6];
        float score[2];
    }student; /*說明結構體變數*/
    if((fp=fopen("test1.txt","w"))==NULL)
    { /*以文本唯寫方式開啟檔案*/
        printf("cannot open file");
        exit(0);
    }
    printf("input data:/n");
    for( i=0;i<2;i++)
    {
        scanf("%s %s %f %f",student.name,student.num,&student.score[0],
        &student.score[1]); /*從鍵盤輸入*/
        fprintf(fp,"%s %s %7.2f %7.2f/n",student.name,student.num,
        student.score[0],student.score[1]); /* 寫入檔案*/
    }
    fclose(fp); /*關閉檔案*/
    if((fp=fopen("test.txt","r"))==NULL)
    { /*以文本唯讀方式重新開啟檔案*/
        printf("cannot open file");
        exit(0);
    }
    printf("output from file:/n");
    while (fscanf(fp,"%s %s %f %f/n",student.name,student.num,&student.score[0],student.score[1])!=EOF)
    / *從檔案讀入* /
        printf("%s %s %7.2f %7.2f/n",student.name,student.num,
    student.score[0],student.score[1]); /* 顯示到螢幕*/
    fclose(fp); /*關閉檔案*/
}
    程式設計一個檔案變數指標,兩次以不同方式開啟同一檔案,寫入和讀出格式化資料,有一點很重要,那就是用什麼格式寫入檔案,就一定用什麼格式從檔案讀,否則,讀出的資料與格式控制符不一致,就造成資料出錯。上述程式運行如下:
input data:
xiaowan j001 87.5 98.4
xiaoli j002 99.5 89.6
output from file:
xiaowan j001 87.50 98.40
xiaoli j002 99.50 89.60

列表檔案的內容顯示為:
c:/>type test.txt
xiaowan j001 87.50 98.40
xiaoli j002 99.50 89.60
    此程式所訪問的檔案也可以定為二進位檔案,若開啟檔案的方式為:
if ((fp=fopen("test1.txt","wb"))==NULL)
{ / * 以二進位唯寫方式開啟檔案* /
    printf("cannot open file");
    exit(0);
}
其效果完全相同。

4. 成塊讀寫
    前面介紹的幾種讀寫檔案的方法,對其複雜的資料類型無法以整體形式向檔案寫入或從檔案讀出。C語言提供成塊的讀寫方式來操作檔案,使其數組或結構體等類型可以進行一次性讀寫。成塊讀寫檔案函數的調用形式為:
    int fread(void *buf,int size,int count,FILE *stream)
    int fwrite(void *buf,int size,int count,FILE *stream)
    fread()函數從stream 指向的流檔案讀取count (欄位數)個欄位,每個欄位為size(欄位長度)個字元長,並把它們放到b u f(緩衝區)指向的字元數組中。
    fread()函數返回實際已讀取的欄位數。若函數調用時要求讀取的欄位數超過檔案存放的欄位數,則出錯或已到檔案尾,實際在操作時應注意檢測。
    fwrite( )函數從buf(緩衝區)指向的字元數組中,把count(欄位數)個欄位寫到stream所指向的流中,每個欄位為size個字元長,函數操作成功時返回所寫欄位數。
    關於成塊的檔案讀寫,在建立檔案時只能以二進位檔案格式建立。

[例8-7] 向磁碟寫入格式化資料,再從該檔案讀出顯示到螢幕。
#i nclude "stdio.h"
#i nclude "stdlib.h"
main( )
{
    FILE *fp1;
    int i;
    struct stu{ / *定義結構體*/
        char name[15];
        char num[6];
        float score[2];
    }student;
    if((fp1=fopen("test.txt","wb"))==NULL)
    { /*以二進位唯寫方式開啟檔案* /
        printf("cannot open file");
        exit(0);
    }
    printf("input data:/n");
    for( i=0;i<2;i++)
    {
        scanf("%s %s %f %f",student.name,student.num,&student.score[0],&student.score[1]); /* 輸入一記錄*/
        fwrite(&student,sizeof(student),1,fp1); /* 成塊寫入檔案*/
    }
    fclose(fp1);
    if((fp1=fopen("test.txt","rb"))==NULL)
    { /*重新以二進位唯寫開啟檔案*/
        printf("cannot open file");
        exit(0);
    }
    printf("output from file:/n");
    for (i=0;i<2;i++)
    {
    fread(&student,sizeof(student),1,fp1); /* 從檔案成塊讀*/
    printf("%s %s %7.2f %7.2f/n",student.name,student.num,student.score[0],student.score[1]); /* 顯示到螢幕*/
    }
    fclose(fp1);
}
運行程式:
input data:
xiaowan j001 87.5 98.4
xiaoli j002 99.5 89.6
output from file:
xiaowan j001 87.50 98.40
xiaoli j002 99.50 89.60
    通常,對於輸入資料的格式較為複雜的話,我們可採取將各種格式的資料當做字串輸入,然後將字串轉換為所需的格式。C提供函數:
    int atoi(char *ptr)
    float atof(char *ptr)
    long int atol(char *ptr)
    它們分別將字串轉換為整型、實型和長整型。使用時請將其包含的標頭檔math.h或stdlib.h寫在程式的前面。

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/jiji262/archive/2007/10/21/1835971.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.