1. 程式人生 > >【轉】 C語言文件操作詳解

【轉】 C語言文件操作詳解

pri void rfi 識別 archive format 隨機 stat 文本文

轉自:http://www.cnblogs.com/likebeta/archive/2012/06/16/2551780.html

C語言中沒有輸入輸出語句,所有的輸入輸出功能都用 ANSI C提供的一組標準庫函數來實現。文件操作標準庫函數有:

      文件的打開操作 fopen 打開一個文件

      文件的關閉操作 fclose 關閉一個文件

      文件的讀寫操作 fgetc 從文件中讀取一個字符
              fputc 寫一個字符到文件中去
              fgets 從文件中讀取一個字符串
              fputs 寫一個字符串到文件中去
              fprintf 往文件中寫格式化數據
              fscanf 格式化讀取文件中數據
              fread 以二進制形式讀取文件中的數據
              fwrite 以二進制形式寫數據到文件中去
              getw 以二進制形式讀取一個整數
              putw 以二進制形式存貯一個整數

    文件狀態檢查函數 feof 文件結束
              ferror 文件讀/寫出錯
              clearerr 清除文件錯誤標誌
              ftell 了解文件指針的當前位置

      文件定位函數 rewind 反繞
              fseek 隨機定位

# 文件的打開
 1.函數原型

FILE *fopen(char *pname,char *mode)

 2.功能說明
   按照mode 規定的方式,打開由pname指定的文件。若找不到由pname指定的相應文件,就按以下方式之一處理:
(1) 此時如mode 規定按寫方式打開文件,就按由pname指定的名字建立一個新文件;
(2) 此時如mode 規定按讀方式打開文件,就會產生一個錯誤。

打開文件的作用是:
(1)分配給打開文件一個FILE 類型的文件結構體變量,並將有關信息填入文件結構體變量;
(2)開辟一個緩沖區;
(3)調用操作系統提供的打開文件或建立新文件功能,打開或建立指定文件;
FILE *:指出fopen是一個返回文件類型的指針函數;

 3.參數說明
pname:是一個字符指針,它將指向要打開或建立的文件的文件名字符串。
mode:是一個指向文件處理方式字符串的字符指針,操作方式如下:

"r" 打開,只讀; "w" 打開,文件指針指到頭,只寫; "a" 打開,指向文件尾,在已存在文件中追加;

"rb" 打開一個二進制文件,只讀; "wb" 打開一個二進制文件,只寫; "ab" 打開一個二進制文件,進行追加 ;

"r+" 以讀/寫方式打開一個已存在的文件; "w+" 以讀/寫方式建立一個新的文本文件 ;

"a+" 以讀/寫方式打開一個文件文件進行追加 ;"rb+" 以讀/寫方式打開一個二進制文件;

"wb+" 以讀/寫方式建立一個新的二進制文件 ;"ab+" 以讀/寫方式打開一個二進制文件進行追加 。

 4.返回值
   正常返回:被打開文件的文件指針。
   異常返回:NULL,表示打開操作不成功。

例如:

//定義一個名叫fp文件指針
FILE *fp;
//判斷按讀方式打開一個名叫test的文件是否失敗
if((fp=fopen("test","r")) == NULL)//打開操作不成功
{
    printf("The file can not be opened.\n");     
    exit(1);//結束程序的執行
}

 要說明的是:C語言將計算機的輸入輸出設備都看作是文件。例如,鍵盤文件、屏幕文件等。ANSI C標準規定,在執行程序時系統先自動打開鍵盤、屏幕、錯誤三個文件。這三個文件的文件指針分別是:標準輸入stdin、標準輸出stdout和標準出錯 stderr。

* 文件的關閉

1. 函數原型

int fclose(FILE *fp);

2. 功能說明
  關閉由fp指出的文件。此時調用操作系統提供的文件關閉功能,關閉由fp->fd指出的文件;釋放由fp指出的文件類型結構體變量;返回操作結果,即0或EOF。

3. 參數說明
  fp:一個已打開文件的文件指針。

4. 返回值
  正常返回:0。
  異常返回:EOF,表示文件在關閉時發生錯誤。
例如:

int n=fclose(fp);

*文件的讀寫操作

A. 從文件中讀取一個字符
  1. 函數原型

int fgetc(FILE *fp);

  2. 功能說明
    從fp所指文件中讀取一個字符。
  3. 參數說明
    fp:這是個文件指針,它指出要從中讀取字符的文件。
  4. 返回值
    正常返回: 返回讀取字符的代碼。
    非正常返回:返回EOF。例如,要從"寫打開"文件中讀取一個字符時,會發生錯誤而返回一個EOF。
  5. 實例

【例8.1】顯示指定文件的內容。

//程序名為:display.c
//執行時可用:display filename1 形式的命令行運行。顯示文件filename1中的內容。例如,執行命令行display display.c將在屏幕上顯示display的原代碼。

//File display program.
#include <stdio.h>
void main(int argc,char *argv[]) //命令行參數
{
    int ch;//定義文件類型指針
    FILE *fp;//判斷命令行是否正確
    if(argc!=2)
    {
        printf("Error format,Usage: display filename1\n");
        return; //鍵入了錯誤的命令行,結束程序的執行
    }
    //按讀方式打開由argv[1]指出的文件
    if((fp=fopen(argv[1],"r"))==NULL)
    {
        printf("The file <%s> can not be opened.\n",argv[1]);//打開操作不成功
        return;//結束程序的執行
    }
    //成功打開了argv[1]所指文件
    ch=fgetc(fp); //從fp所指文件的當前指針位置讀取一個字符
    while(ch!=EOF) //判斷剛讀取的字符是否是文件結束符
    {
        putchar(ch); //若不是結束符,將它輸出到屏幕上顯示
        ch=fgetc(fp); //繼續從fp所指文件中讀取下一個字符
    } //完成將fp所指文件的內容輸出到屏幕上顯示
    fclose(fp); //關閉fp所指文件
}

B. 寫一個字符到文件中去

1. 函數原型

int fputc(int ch,FILE *fp)

2. 功能說明
  把ch中的字符寫入由fp指出的文件中去。
3. 參數說明
  ch:是一個整型變量,內存要寫到文件中的字符(C語言中整型量和字符量可以通用)。
  fp:這是個文件指針,指出要在其中寫入字符的文件。
4. 返回值
  正常返回: 要寫入字符的代碼。
  非正常返回:返回EOF。例如,要往"讀打開"文件中寫一個字符時,會發生錯誤而返回一個EOF。
5. 實例

【例8.2】將一個文件的內容復制到另一個文件中去。

//程序名為:copyfile.c
//執行時可用:copyfile filename1 filename2形式的命令行運行,將文件filename1中的內容復制到文件filename2中去。
//file copy program.
#include <stdio.h>
void main(int argc,char *argv[]) //命令行參數
{
    int ch;
    FILE *in,*out; //定義in和out兩個文件類型指針
    if(argc!=3) //判斷命令行是否正確
    {
        printf("Error in format,Usage: copyfile filename1 filename2\n");
        return; //命令行錯,結束程序的執行
    }
    //按讀方式打開由argv[1]指出的文件
    if((in=fopen(argv[1],"r"))==NULL)
    {
        printf("The file <%s> can not be opened.\n",argv[1]);
        return; //打開失敗,結束程序的執行
    }
    //成功打開了argv[1]所指文件,再
    //按寫方式打開由argv[2]指出的文件
    if((out=fopen(argv[2],"w"))==NULL)
    {
        printf("The file %s can not be opened.\n",argv[2]);
        return; //打開失敗,結束程序的執行
    }
    //成功打開了argv[2]所指文件
    ch=fgetc(in); //從in所指文件的當前指針位置讀取一個字符
    while(ch!=EOF) //判斷剛讀取的字符是否是文件結束符
    {
        fputc(ch,out); //若不是結束符,將它寫入out所指文件
        ch=fgetc(in); //繼續從in所指文件中讀取下一個字符
    } //完成將in所指文件的內容寫入(復制)到out所指文件中
    fclose(in); //關閉in所指文件
    fclose(out); //關閉out所指文件
}

【例8.3】按十進制和字符顯示文件代碼,若遇不可示字符就用井號"#"字符代替之。

//程序名為:dumpf.c
//執行時可用:dumpf filename1 形式的命令行運行。
// File dump program.
#include <stdio.h>
void main(int argc,char *argv[])
{
    char str[9];
    int ch,count,i;
    FILE *fp;
    if(argc!=2)
    {
        printf("Error format,Usage: dumpf filename\n");
        return;
    }
    if((fp=fopen(argv[1],"r"))==NULL)
    {
        printf("The file %s can not be opened.\n",argv[1]);
        return;
    }
    count=0;
    do{
        i=0;
        //按八進制輸出第一列,作為一行八個字節的首地址
        printf("%06o: ",count*8);
        do{
            // 從打開的文件中讀取一個字符
            ch=fgetc(fp);
            // 按十進制方式輸出這個字符的ASCII碼
            printf("%4d",ch);
            // 如果是不可示字符就用"#"字符代替
            if(ch<‘ ‘||ch>‘~‘) str[i]=‘#‘;
            // 如果是可示字符,就將它存入數組str以便形成字符串
            else str[i]=ch;
            // 保證每一行輸出八個字符
            if(++i==8) break;
        }while(ch!=EOF); // 遇到文件尾標誌,結束讀文件操作
        str[i]=‘\0‘; // 在數組str加字符串結束標誌
        for(;i<8;i++) printf(" "); // 一行不足八個字符用空格填充
        printf(" %s\n",str); // 輸出字符串
        count++; // 準備輸出下一行
    }while(ch!=EOF); // 直到文件結束
    fclose(fp); // 關閉fp所指文件
}

C. 從文件中讀取一個字符串

1. 函數原型
  char *fgets(char *str,int n,FILE *fp)
2. 功能說明
  從由fp指出的文件中讀取n-1個字符,並把它們存放到由str指出的字符數組中去,最後加上一個字符串結束符‘\0‘。
3. 參數說明
  str:接收字符串的內存地址,可以是數組名,也可以是指針。
  n: 指出要讀取字符的個數。
  fp:這是個文件指針,指出要從中讀取字符的文件。
4. 返回值

正常返回:返回字符串的內存首地址,即str的值。
非正常返回:返回一個NULL值,此時應當用feof()或ferror()函數來判別是讀取到了文件尾,還是發生了錯誤。例如,要從"寫打開"文件中讀取字符串,將
發生錯誤而返回一個NULL值。

D. 寫一個字符串到文件中去

1. 函數原型

int fputs(char *str,FILE *fp)

2. 功能說明
  把由str指出的字符串寫入到fp所指的文件中去。
3. 參數說明
  str:指出要寫到文件中去的字符串。
  fp:這是個文件指針,指出字符串要寫入其中的文件。
4. 返回值
  正常返回: 寫入文件的字符個數,即字符串的長度。
  非正常返回:返回一個NULL值,此時應當用feof()或ferror()函數來判別是讀取到了文件尾,還是發生了錯誤。例如,要往一個"讀打開" 文件中寫字符串時,
會發生錯誤而返回一個NULL值。

5.實例

【例8.4】以下程序將一個文件的內容附加到另一個文件中去。

//程序名:linkfile.c
//執行時可用:linkfile filename1 filename2形式的命令行運行,將文件filename2的內容附加在文件filename1之後。
// file linked program.
#include <stdio.h>
#define SIZE 512
void main(int argc,char *argv[])
{
    char buffer[SIZE];
    FILE *fp1,*fp2;
    if(argc!=3)
    {
        printf("Usage: linkfile filename1 filename2\n");
        return;
    }
    // 按追加方式打開argv[1] 所指文件
    if((fp1=fopen(argv[1],"a"))==NULL)
    {
        printf("The file %s can not be opened.\n",argv[1]);
        return;
    }
    if((fp2=fopen(argv[2],"r"))==NULL)
    {
        printf("The file %s can not be opened.\n",argv[2]);
        return;
    }
    // 讀入一行立即寫出,直到文件結束
    while(fgets(buffer,SIZE,fp1)!=NULL)
        printf("%s\n",buffer);
    while(fgets(buffer,SIZE,fp2)!=NULL)
        fputs(buffer,fp1);
    fclose(fp1);
    fclose(fp2);
    if((fp1=fopen(argv[1],"r"))==NULL)
    {
        printf("The file %s can not be opened.\n",argv[1]);
        return;
    }
    while(fgets(buffer,SIZE,fp1)!=NULL)
        printf("%s\n",buffer);
    fclose(fp1);
}

E. 往文件中寫格式化數據

1.函數原型

int fprintf(FILE *fp,char *format,arg_list)

2.功能說明
  將變量表列(arg_list)中的數據,按照format指出的格式,寫入由fp指定的文件。fprintf()函數與printf()函數的功能相同,只是printf()函數是將數據寫入屏幕文件(stdout)。
3.參數說明
  fp:這是個文件指針,指出要將數據寫入的文件。
  format:這是個指向字符串的字符指針,字符串中含有要寫出數據的格式,所以該字符串成為格式串。格式串描述的規則與printf()函數中的格式串相同。
arg_list:是要寫入文件的變量表列,各變量之間用逗號分隔。
4.返回值
  無。
5. 實例

【8.5】下列程序的執行文件為display.exe,執行時鍵入命令行:
   display [-i][-s] filename
下面的表格列出了命令行參數的含義及其功能:

//存儲文件名:save.txt
//程序代碼如下:
// file display program.
#include <stdio.h>
void main()
{
    char name[10];
    int nAge,nClass;
    long number;
    FILE *fp;
    if((fp=fopen("student.txt","w"))==NULL)
    {
        printf("The file %s can not be opened.\n","student.txt");
        return;
    }
    fscanf(stdin,"%s %d %d %ld",name,&nClass,&nAge,&number);
    fprintf(fp,"%s %5d %4d %8ld",name,nClass,nAge,number);
    fclose(fp);
    if((fp=fopen("student.txt","r"))==NULL)
    {
        printf("The file %s can not be opened.\n","student.txt");
        return;
    }
    fscanf(fp,"%s %d %d %ld",name,&nClass,&nAge,&number);
    printf("name nClass nAge number\n");
    fprintf(stdout,"%-10s%-8d%-6d%-8ld\n",name,nClass,nAge,number);
    fclose(fp);
}

G. 以二進制形式讀取文件中的數據

1. 函數原型

int fread(void *buffer,unsigned sife,unsigned count,FILE *fp)

2. 功能說明
  從由fp指定的文件中,按二進制形式將sife*count個數據讀到由buffer指出的數據區中。
3. 參數說明
buffer:這是一個void型指針,指出要將讀入數據存放在其中的存儲區首地址。
sife:指出一個數據塊的字節數,即一個數據塊的大小尺寸。
count:指出一次讀入多少個數據塊(sife)。
fp:這是個文件指針,指出要從其中讀出數據的文件。
4.返回值
  正常返回:實際讀取數據塊的個數,即count。
  異常返回:如果文件中剩下的數據塊個數少於參數中count指出的個數,或者發生了錯誤,返回0值。此時可以用feof()和ferror()來判定到底出現了什麽
情況。

H. 以二進制形式寫數據到文件中去

1. 函數原型

int fwrite(void *buffer,unsigned sife,unsigned count,FILE *fp)

2. 功能說明
  按二進制形式,將由buffer指定的數據緩沖區內的sife*count個數據寫入由fp指定的文件中去。
3. 參數說明
buffer:這是一個void型指針,指出要將其中數據輸出到文件的緩沖區首地址。
sife:指出一個數據塊的字節數,即一個數據塊的大小尺寸。
count:一次輸出多少個數據塊(sife)。
fp:這是個文件指針,指出要從其中讀出數據的文件。
4.返回值
  正常返回:實際輸出數據塊的個數,即count。
  異常返回:返回0值,表示輸出結束或發生了錯誤。
5.實例

【例8.7】

#include <stdio.h>
#define SIZE 4
struct worker
{ int number;
    char name[20];
    int age;
};
void main()
{
    struct worker wk;
    int n;
    FILE *in,*out;
    if((in=fopen("file1.txt","rb"))==NULL)
    {
        printf("The file %s can not be opened.\n","file1.txt");
        return;
    }
    if((out=fopen("file2.txt","wb"))==NULL)
    {
        printf("The file %s can not be opened.\n","file2.txt");
        return;
    }
    while(fread(&wk,sizeof(struct worker),1,in)==1)
        fwrite(&wk,sizeof(struct worker),1,out);
    fclose(in);
    fclose(out);
}

I. 以二進制形式讀取一個整數

1. 函數原型

int getw(FILE *fp)

2. 功能說明
  從由fp指定的文件中,以二進制形式讀取一個整數。
3. 參數說明
  fp:是文件指針。
4. 返回值
  正常返回:所讀取整數的值。
  異常返回:返回EOF,即-1。由於讀取的整數值有可能是-1,所以必須用feof()或ferror()來判斷是到了文件結束,還是出現了一個出錯。
5. 實例

【例8.8】

#include <stdio.h>
void main(int argc,char *argv[])
{
    int i,sum=0;
    FILE *fp;
    if(argc!=2)
    {
        printf("Command error,Usage: readfile filename\n");
        exit(1);
    }
    if(!(fp=fopen(argv[1],"rb")))
    {
        printf("The file %s can not be opened.\n",argv[1]);
        exit(1);
    }
    for(i=1;i<=10;i++) sum+=getw(fp);
    printf("The sum is %d\n",sum);
    fclose(fp);
}

J. 以二進制形式存貯一個整數

1.函數原型

int putw(int n,FILE *fp)

2. 功能說明
 以二進制形式把由變量n指出的整數值存放到由fp指定的文件中。
3. 參數說明
 n:要存入文件的整數。
 fp:是文件指針。
4. 返回值
 正常返回:所輸出的整數值。
 異常返回:返回EOF,即-1。由於輸出的整數值有可能是-1,所以必須用feof()或ferror()來判斷是到了文件結束,還是出現了一個出錯。
5. 實例

【例8.9】

#include <stdio.h>
void main(int argc,char *argv[])
{
    int i;
    FILE *fp;
    if(argc!=2)
    {
        printf("Command error,Usage: writefile filename\n");
        return;
    }

    if(!(fp=fopen(argv[1],"wb")))
    {
        printf("The file %s can not be opened.\n",argv[1]);
        return;
    }
    for(i=1;i<=10;i++) printf("%d\n", putw(i,fp));
    fclose(fp);
}

* 文件狀態檢查

A. 文件結束
(1) 函數原型

int feof(FILE *fp)

(2) 功能說明
   該函數用來判斷文件是否結束。
(3) 參數說明
   fp:文件指針。
(4) 返回值
   0:假值,表示文件未結束。
   1:真值,表示文件結束。
(5) 實例

【例8.10】

#include <stdio.h>
void main(int argc,char *argv[])
{
    FILE *in,*out;
    char ch;
    if(argc!=3)
    {
        printf("Usage: copyfile filename1 filename2\n");
        return;
    }
    if((in=fopen(argv[1],"rb"))==NULL)
    {
        printf("The file %s can not be opened.\n",argv[1]);
        return;
    }
    if((out=fopen(argv[2],"wb"))==NULL)
    {
        printf("The file %s can not be opened.\n",argv[2]);
        return;
    }
    while(!feof(in))
    {
        ch=fgetc(in);
        if(ferror(in))
        {
            printf("read error!\n");
            clearerr(in);
        }
        else
        {
            fputc(ch,out);
            if(ferror(out))
            {
                printf("write error!\n");
                clearerr(out);
            }
        }
    }
    fclose(in);
    fclose(out);
}

B. 文件讀/寫出錯
(1) 函數原型

int ferror(FILE *fp)

(2) 功能說明
   檢查由fp指定的文件在讀寫時是否出錯。
(3) 參數說明
   fp:文件指針。
(4) 返回值
   0:假值,表示無錯誤。
   1:真值,表示出錯。

C. 清除文件錯誤標誌

(1) 函數原型

void clearerr(FILE *fp)

(2) 功能說明
   清除由fp指定文件的錯誤標誌。
(3) 參數說明
   fp:文件指針。
(4) 返回值
   無。
(5) 實例

【例8.12】

#include <stdio.h>
void main(int argc,char *argv[])
{
    FILE *in,*out;
    char ch;
    if(argc!=3)
    {
        printf("Usage: copyfile filename1 filename2\n");
        return;
    }
    if((in=fopen(argv[1],"rb"))==NULL)
    {
        printf("The file %s can not be opened.\n",argv[1]);
        return;
    }
    if((out=fopen(argv[2],"wb"))==NULL)
    {
        printf("The file %s can not be opened.\n",argv[2]);
        return;
    }
    while(!feof(in))
    {
        ch=fgetc(in);
        if(ferror(in))
        {
            printf("read error!\n");
            clearerr(in);
        }
        else
        {
            fputc(ch,out);
            if(ferror(out))
            {
                printf("write error!\n");
                clearerr(out);
            }
        }
    }
    fclose(in);
    fclose(out);
}

D. 了解文件指針的當前位置
(1) 函數原型

long ftell(FILE *fp)

(2) 功能說明
   取得由fp指定文件的當前讀/寫位置,該位置值用相對於文件開頭的位移量來表示。
(3) 參數說明
   fp:文件指針。
(4) 返回值
   正常返回:位移量(這是個長整數)。
   異常返回:-1,表示出錯。
(5) 實例

* 文件定位

A. 反繞
(1) 函數原型

void rewind(FILE *fp)

(2) 功能說明
   使由文件指針fp指定的文件的位置指針重新指向文件的開頭位置。
(3) 參數說明
   fp:文件指針。
(4) 返回值
   無。
(5) 實例

【例8.14】

#include <stdio.h>
void main()
{
    FILE *in,*out;
    in=fopen("filename1","r");
    out=fopen("filename2","w");
    while(!feof(in)) fputc(fgetc(in),out);
    rewind(out);
    while(!feof(in)) putchar(fgetc(in));
    fclose(in);
    fclose(out);
}

B. 隨機定位
(1) 函數原型

int fseek(FILE *fp,long offset,int base)

(2) 功能說明
   使文件指針fp移到基於base的相對位置offset處。
(3)參數說明
   fp:文件指針。
   offset:相對base的字節位移量。這是個長整數,用以支持大於64KB的文件。
   base:文件位置指針移動的基準位置,是計算文件位置指針位移的基點。ANSI C定義了base的可能取值,以及這些取值的符號常量。

(4)返回值

  正常返回:當前指針位置。
  異常返回:-1,表示定位操作出錯。

(5)實例
【例8.15】

#include <stdio.h>
#include <string.h>
struct std_type
{
    int num;
    char name[20];
    int age;
    char class;
}stud;
int cstufile()
{
    int i;
    FILE *fp;
    if((fp=fopen("stufile","wb"))==NULL)
    {
        printf("The file can‘t be opened for write.\n");
        return 0;
    }
    for(i=1;i<=100;i++)
    {
        stud.num=i;
        strcpy(stud.name,"aaaa");
        stud.age=17;
        stud.class=‘8‘;
        fwrite(&stud,sizeof(struct std_type),1,fp);
    }
    fclose(fp);
    return 1;
}
void main()
{
    int n;
    FILE *fp;
    if(cstufile()==0) return;
    if((fp=fopen("stufile","rb"))==NULL)
    {
        printf("The file can not be opened.\n");
        return;
    }
    for(n=0;n<100;n+=2)
    {
        fseek(fp,n*sizeof(struct std_type),SEEK_SET);
        fread(&stud,sizeof(struct std_type),1,fp);
        printf("%10d%20s%10d%4c\n",stud.num,stud.name,stud.age,stud.class);
    }
    fclose(fp);
}

* 關於exit()函數
1. 函數原型

void exit(int status)

2. 功能說明
  exit()函數使程序立即終止執行,同時將緩沖區中剩余的數據輸出並關閉所有已經打開的文件。
3. 參數說明
  status:為0值表示程序正常終止,為非0值表示一個定義錯誤。
4. 返回值
  無。

* 關於feof()函數
1. 函數原型

int feof(FILE *fp)

2. 功能說明
   在文本文件(ASCII文件)中可以用值為-1的符號常量EOF來作為文件的結束符。但是在二進制文件中-1往往可能是一個有意義的數據,因此不能用它 來作為文件的結束標誌。為了能有效判別文件是否結束,ANSI C提供了標準函數feof(),用來識別文件是否結束。
3. 參數說明
  fp:文件指針。
4. 返回值
  返回為非0值:已到文件尾。
  返回為0值:表示還未到文件尾。

【轉】 C語言文件操作詳解