程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言文件操作解析(三)

C語言文件操作解析(三)

編輯:關於C語言

 

在前面已經討論了文件打開操作,下面說一下文件的讀寫操作。文件的讀寫操作主要有4種,字符讀寫、字符串讀寫、塊讀寫以及格式化讀寫。

一.字符讀寫

    字符讀寫主要使用兩個函數fputc和fgetc,兩個函數的原型是:

    int fputc(int ch,FILE *fp);若寫入成功則返回寫入的字符,否則返回-1

    int fgetc(FILE *fp);  若讀取成功則返回讀取的字符,否則返回-1

注意:1)對於fputc函數和fgetc函數,每次操作,fputc只能寫入1個字節的數據,無論參數ch多大,只將其低8位的數據寫入到文件中;fgetc 每次只能返回一個字節的數據。

        2)對於fgetc函數,若讀取成功則返回讀取到的字符,否則返回-1.這裡面返回-1(即EOF)有兩種情況:一種是讀到文件結束已經沒有任何字符可供讀取了,另一種是讀取出錯。由於通常情況下,在文本文件中可顯字符是不可能出現ASCII碼為-1的字符,因此可以通過fgetc的返回結果判斷文件是否結束(讀取不出錯的情況下)。但是在二進制文件中則不能這麼判斷了,因為二進制文件中很可能就含有FF這樣的數據,如果將存儲fgetc讀取結果的變量ch定義為char型,則不能判斷二進制文件是否結束,但是如果定義為int型,則同樣可以判斷,因為即使讀取的字符是FF,但是由於ch是int型,則事實上ch=0x000000FF,並不等於-1,因此可以判斷文件是否結束。(注意以上所述只在文件讀取不出錯的情況下成立,若文件讀取出錯,是不能這麼判斷文件是否結束,必須通過feof()函數來判斷)

測試程序:

	#include<stdio.h>
#include<stdlib.h>

int main(void)
{
    FILE *fp;
    int ch;
    if((fp=fopen("test.txt","wb+"))==NULL)
    {
        printf("can not open file\n");
        exit(0);
    }
    fputc(-1,fp);          //-1的二進制為FF
    fputc(385,fp);         //385二進制為110000001
    rewind(fp);
    ch=fgetc(fp);
    while(feof(fp)==0)
    {
        printf("%d\n",ch);
        ch=fgetc(fp);
    }
    fclose(fp);
    return 0;
}

執行結果為:

255
129
Press any key to continue

由於fputc每次只寫入一個字節的數據,因此雖然第二次想寫入385,但是只將其低8位數據寫入,所以輸出結果為129.

若將上述程序中的ch定義為char型,則執行結果為:

-1
-127
Press any key to continue

原因上面已經解釋了.

二.字符串讀寫

    字符串讀寫主要涉及到兩個函數fputs和fgets,這兩個函數的原型是:

    int fputs(const char *s,FILE *fp);

    char *fgets(char *s,int n,FILE *fp);

    對於fputs函數,將字符串寫入文件,若寫入成功則返回一個非負值,否則返回-1;

    對於fgets函數,從文件中讀取不超過n-1個字符到字符數組中(若文件中字符少於n-1個,則只讀取文件中存在的字符),系統在字符數組末尾自動添加一個'\0',返回字符數組的首地址。

注意:1)對於fgets函數,在讀取過程中,若讀取到字符'\n',則讀取過程提前結束。

測試程序:

	#include<stdio.h>
#include<stdlib.h>

int main(void)
{
    FILE *fp;
    char s[10];
    if((fp=fopen("test.txt","wb+"))==NULL)
    {
        printf("can not open file\n");
        exit(0);
    }
    fputc('A',fp);
    fputc('B',fp);
    fputc('\n',fp);
    fputc('C',fp);
    rewind(fp);
    fgets(s,5,fp);
    printf("%s\n",s);
    fclose(fp);
    return 0;
}

執行結果為:

AB

Press any key to continue

由此可知當讀取到換行符'\n'時便停止讀取了。

三.塊讀寫

    塊讀寫主要涉及到兩個函數fread和fwrite,這兩個函數的原型是:

    unsigned int fread(void *buffer,unsigned int size,unsigned int n,FILE *fp);

   從文件讀取一組數據存放在首地址為buffer的內存空間中,size為一個數據塊的大小,n為要讀取的數據塊的個數,若讀取成功,則返回讀取的數據的數據塊的個數,否則返回0.

    unsigned int fwrite(const void *buffer,unsigned int size,unsigned int n,FILE *fp);

    向文件中寫入數據,寫入成功返回寫入數據塊的個數,否則返回0.

    塊讀寫一般用於結構體。

注意:1)塊讀寫常用於結構體。

       2)fread和fwrite一般成對出現,如果對文件進行寫操作用的是fwrite,則用fread讀取,否則可能會得到意想不到的結果。

測試程序:

	#include<stdio.h>
#include<stdlib.h>

typedef struct node
{
    char name[20];
    double score;
    int age;
}Student;

int main(void)
{
    FILE *fp;
    int i;
    Student s1[3]={{"liudehua",85.5,45},{"zhangxueyou",79.3,47},{"guofucheng",83.4,43}};
    Student s2[3];
    if((fp=fopen("test.txt","wb+"))==NULL)
    {
        printf("can not open file\n");
        exit(0);
    }
    printf("%d\n",fwrite(s1,sizeof(Student),3,fp));    
    //printf("%d\n",fwrite(s1,sizeof(s1),1,fp));    //注意和上一句的區別
     rewind(fp);
    printf("%d\n",fread(s2,sizeof(Student),3,fp));
    for(i=0;i<3;i++)
    {
        printf("%s %lf %d\n",s2[i].name,s2[i].score,s2[i].age);
    }
    fclose(fp);
    return 0;
}

執行結果為:

3
3
liudehua 85.500000 45
zhangxueyou 79.300000 47
guofucheng 83.400000 43
Press any key to continue

四.格式化讀寫

  格式化讀寫主要涉及到兩個函數:fscanf和fprintf,兩個函數的原型是

  int fscanf(FILE *fp,const char *format[,argument]....);

  用於從文件格式化讀取數據,若讀取成功,則返回讀取的數據個數,否則返回-1

  int fprintf(FILE *fp,const char *format[,argument]....);

  用於向文件格式化寫入數據,若寫入成功,則返回寫入的字符個數,否則返回-1

注意:1)格式化讀寫和其他幾種讀寫有很大的不同。格式化讀寫是以我們人所能識別的格式將數據寫入文件,即若以格式化方式寫入一個整型數值65,則其實是寫入的兩個字符'6'和'5',即占2字節,而不是4字節,但是若以塊寫方式寫入,則其占4字節。即在使用格式化讀寫時系統自動進行了一些轉換。

      2)fprintf和fscanf函數一般成對出現,若數據是用fprintf進行寫入的,則最好使用fscanf進行讀取。

      3)在使用fprintf函數寫入時,若文件是以文本方式打開,如果參數format中包含了'\n',則最後文件中會被寫入換行符;而若文件以二進制方式打開,則文件中不會被寫入換行符,這點區別在上一篇博客中已經提到。

測試程序:

	#include<stdio.h>
#include<stdlib.h>

typedef struct node
{
    char name[20];
    double score;
    int age;
}Student;

int main(void)
{
    FILE *fp;
    int i;
    Student s1[3]={{"liudehua",85.5,45},{"zhangxueyou",79.3,47},{"guofucheng",83.4,43}};
    Student s2[3];
    if((fp=fopen("test.txt","wb+"))==NULL)
    {
        printf("can not open file\n");
        exit(0);
    }
    for(i=0;i<3;i++)
    {
        printf("%d\n",fprintf(fp,"%s %lf %d\n",s1[i].name,s1[i].score,s1[i].age));
    }
    rewind(fp);
    for(i=0;i<3;i++)
    {
        printf("%d\n",fscanf(fp,"%s %lf %d",s2[i].name,&s2[i].score,&s2[i].age));
    }
    for(i=0;i<3;i++)
    {
        printf("%s %lf %d\n",s2[i].name,s2[i].score,s2[i].age);
    }
    fclose(fp);
    return 0;
}

執行結果:

22
25
24
3
3
3
liudehua 85.500000 45
zhangxueyou 79.300000 47
guofucheng 83.400000 43
Press any key to continue

文件test.txt中的內容是:

\

若將打開方式改成"wt+",則文件中的內容為:

\

而若以fread和fwrite方式進行讀寫時,其結果如下:

測試程序:

	#include<stdio.h>
#include<stdlib.h>

typedef struct node
{
    char name[20];
    double score;
    int age;
}Student;

int main(void)
{
    FILE *fp;
    Student s1[3]={{"liudehua",85.5,45},{"zhangxueyou",79.3,47},{"guofucheng",83.4,43}};
    if((fp=fopen("test.txt","wt+"))==NULL)
    {
        printf("can not open file\n");
        exit(0);
    }
    fwrite(s1,sizeof(s1),1,fp);
    fclose(fp);
    return 0;
}

則文件中的內容為:

\

從這裡就可以看出格式化讀寫跟其他方式的區別。

測試程序:

	#include<stdio.h>
#include<stdlib.h>

int main(void)
{
    FILE *fp;
    int n=32768;
    if((fp=fopen("test.txt","wt+"))==NULL)
    {
        printf("can not open file\n");
        exit(0);
    }
    fwrite(&n,sizeof(int),1,fp);
    fclose(fp);
    return 0;
}

執行後,用二進制方式打開文件:

\

而32768的二進制為00000000100000000000000即00 80 00 00,內容占4個字節。

	#include<stdio.h>
#include<stdlib.h>

int main(void)
{
    FILE *fp;
    int n=32768;
    if((fp=fopen("test.txt","wt+"))==NULL)
    {
        printf("can not open file\n");
        exit(0);
    }
    fprintf(fp,"%d",n);
    fclose(fp);
    return 0;
}

執行的結果:

\

即用fprintf寫入的是51,50,55,54,56,即跟字符'3','2','7','6','8'各自對應的整數值,內容占5個字節

作者 海 子

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved