1. 程式人生 > >C流式檔案操作

C流式檔案操作

關鍵字:

普通檔案、裝置檔案;

檔案檔案、二進位制檔案;

流式檔案

FILE *

字元讀寫、串讀寫、塊讀寫、格式化讀寫。

換行符,EOF,串結束符

隨機讀寫

檔案的基本概念

  所謂"檔案"是指一組相關資料的有序集合。檔案通常是駐留在外部介質(如磁碟等)上的, 在使用時才調入記憶體中來。從不同的角度可對檔案作不同的分類。

從使用者的角度看,分為普通檔案和裝置檔案:

  普通檔案 是指駐留在磁碟或其它外部介質上的一個有序資料集。可以是原始檔、目標檔案、可執行程式(可以稱作程式檔案);也可以是一組待輸入處理的原始資料,或者是一組輸出的結果(可稱作資料檔案)。

  裝置檔案 是指與主機相聯的各種外部裝置,如顯示器、印表機、鍵盤等。在作業系統中,把外部裝置也看作是一個檔案來進行管理,把它們的輸入、輸出等同於對磁碟檔案的讀和寫。 通常把顯示器定義為標準輸出檔案,相關函式有printf,putchar

等。鍵盤通常被指定標準的輸入檔案,相關函式有scanf,getchar等。

從檔案編碼的方式來看,分為ASCII碼檔案和二進位制碼檔案:

  ASCII檔案也稱為文字檔案,這種檔案在磁碟中存放時每個字元對應一個位元組,用於存放對應的ASCII碼。

例如,數5678的儲存形式為:

BYTE:  00110101 00110110 00110111 00111000

     ↓↓

ASCII:  '5''6''7''8'

共佔用4個位元組。ASCII碼檔案可在螢幕上按字元顯示,例如源程式檔案就是ASCII檔案,用DOS命令TYPE檢視檔案的內容。

  二進位制檔案是按二進位制的編碼方式來存放檔案的。 

例如,數5678

的儲存形式為: 

00010110 00101110

只佔二個位元組。

C系統在處理這些檔案時,並不區分型別,都看成是字元流,按位元組進行處理。輸入輸出字元流的開始和結束只由程式控制而不受物理符號(如回車符)的控制。 因此也把這種檔案稱作"流式檔案"。 // C語言中還有 IO型檔案

本節學習流式檔案的開啟、關閉、讀、寫、 定位等各種操作。

在講這些函式之間,先了解一個概念 FILE

檔案指標

在C語言中用一個指標變數指向一個檔案,通過檔案指標可對檔案進行各種操作。 

FILE* 指標變數識別符號; 

其中

FILE,是由系統定義的一個結構, 該結構中含有檔名、檔案狀態和檔案當前位置等資訊。 各種檔案操作函式已經封裝了對它的操作,使用者程式設計操作檔案時不必關心FILE

結構的細節。

例如:

FILE *fp; 表示fp是指向FILE結構的指標變數,通過fp 即可找存放某個檔案資訊的結構變數,然後按結構變數提供的資訊找到該檔案, 實施對檔案的操作。FILE結構關聯一個檔案,開啟檔案時建立此關聯,關閉檔案時斷開關聯。習慣上把fp稱為指向一個檔案的指標。

流式檔案 開啟和關閉函式

檔案的開啟與關閉檔案在進行讀寫操作之前要先開啟,使用完畢要關閉。 所謂開啟檔案,實際上是建立檔案的各種有關資訊, 並使檔案指標指向該檔案,以便進行其它操作。關閉檔案則斷開指標與檔案之間的聯絡,也就禁止再對該檔案進行操作。

檔案開啟函式 fopen

檔案指標名=fopen(檔名,使用檔案方式

其中

"檔案指標名是被說明為FILE 型別的指標變數。

"檔名是被開啟檔案的檔名, 是字串常量或字元陣列。

"使用檔案方式"是指檔案的型別和操作要求。

例如:

在當前目錄下開啟檔案file a, 只允許進行""操作。

FILE *fp

fp=("fileA","r");

例如:

開啟C驅動器磁碟的根目錄下的檔案hzk16, 這是一個二進位制檔案,只允許按二進位制方式進行讀操作。

FILE *fphzk

fphzk=("c:\\hzk16","rb")

使用檔案的方式共有12

方式

意 義

"rt"

只讀開啟 文字檔案

"wt"

只寫開啟或建立 文字檔案

"at"

追加開啟 文字檔案

"rb"

只讀開啟 二進位制檔案

"wb"

只寫開啟或建立 二進位制檔案

"ab"

追加開啟 二進位制檔案

"rt+"

讀寫開啟 文字檔案

"wt+"

讀寫開啟或建立 文字檔案

"at+"

讀寫開啟文字檔案,可追加

"rb+"

讀寫開啟二進位制檔案

"wb+"

讀寫開啟或建立二進位制檔案

"ab+"

讀寫開啟二進位制檔案,可追加

說明:

1. 檔案使用方式由r,w,a,t,b+六個字元拼成,各字元的含義是:

r(read)   

w(write)  

a(append) 追加

+        讀和寫

t(text)    文字檔案,可省略不寫

b(banary) 二進位制檔案

2. 用"r"開啟的檔案只能讀,且檔案必須已經存在。

3. 用"w"開啟的檔案只能寫。 若檔案不存在,建立之,否則,覆蓋之。

4. "a"開啟的檔案只能寫,內容追加。檔案必須已經存在,否則出錯。

5. 開啟檔案出錯時,fopen將返回 NULL

6. 對於文字檔案,讀入記憶體時轉換為二進位制形式,寫入硬碟時轉換為文字形式,轉換需要一點點時間。對二進位制檔案的讀寫不存在這種轉換。

7. 檔案使用完畢,應關閉之,以避免資料丟失等錯誤。

8. 標準輸入檔案(鍵盤),標準輸出檔案(顯示器 ),標準出錯輸出(出錯資訊)由系統開啟,可直接使用。

檔案關閉函式fclose

fclose(檔案指標); 

正常關閉時返回0,否則返回非零。

流式檔案的讀寫

C提供多種檔案讀寫的函式:

·字元讀寫函式 :fgetcfputc

·字串讀寫函式:fgetsfputs

·資料塊讀寫函式:freedfwrite

·格式化讀寫函式:fscanffprinf

檔案操作函式說明在標頭檔案stdio.h

字元讀寫函式 fgetc, fputc

一、讀字元函式fgetc

  字元變數=fgetc(檔案指標); 

例如:

ch=fgetc(fp); 

說明:

可連續多次使用fgetc函式,讀取多個字元。在檔案內部有一個位置指標,指向檔案的當前讀寫位元組。在檔案開啟時,該指標總是指向檔案的第一個位元組。使用fgetc函式後,該位置指標將向後移動一個位元組。 

應區別 檔案指標和檔案內部的位置指標不是一回事。

檔案指標 是指向整個檔案的,須在程式中定義說明,只要不重新賦值,檔案指標的值是不變的。

檔案內部的位置指標 用以指示檔案內部的當前讀寫位置,每讀寫一次,該指標均向後移動,它不需在程式中定義說明,而是由系統自動設定的。

二、寫字元函式fputc

fputc(字元量,檔案指標); 

其中,待寫入的字元量可以是字元常量或變數

例如:

fputc('a',fp);

說明:

1. 被寫入的檔案可以用寫、讀寫、追加方式開啟,用寫或讀寫方式開啟一個已存在的檔案時將清除原有的檔案內容,寫入字元從檔案首開始。被寫入的檔案若不存在,則建立該檔案。

2. 每寫入一個字元,檔案內部位置指標向後移動一個位元組。

3. fputc函式有一個返回值,如寫入成功則返回寫入的字元, 否則返回一個EOF

字元讀寫示例:

從鍵盤輸入一行字元,寫入一個檔案, 再把該檔案內容讀出顯示在螢幕上。 

#include<stdio.h>

main()
{
FILE *fp;
char ch;

if((fp=fopen("string","wt+"))==NULL)
{
printf("Cannot open file strike any key exit!");
//getch();
exit(1);
}

printf("input a string:\n");
ch=getchar();
while (ch!='\n')
{
fputc(ch,fp);
ch=getchar();
}

rewind(fp);

ch=fgetc(fp);
while(ch!=EOF)
{
putchar(ch);
ch=fgetc(fp);
}
printf("\n");

fclose(fp);
}

字元讀寫示例:
把命令列引數中的前一個檔名標識的檔案, 複製到後一個檔名標識的檔案中, 如命令列中只有一個檔名則把該檔案寫到標準輸出檔案(顯示器)中。

#include<stdio.h>

main(int argc,char *argv[])
{
FILE *fp1,*fp2;
char ch;

if(argc==1)
{
printf("無檔名,請至少指定輸入檔案!");
//getch();
exit(0);
}

if((fp1=fopen(argv[1],"rt"))==NULL)
{
printf("不能開啟輸入檔案 %s\n",argv[1]);
//getch();
exit(1);
}

if(argc==2) 
   fp2=stdout;
else if((fp2=fopen(argv[2],"wt+"))==NULL)
{
printf("不能開啟輸出檔案 %s\n",argv[1]);
//getch();
exit(1);
}

while((ch=fgetc(fp1))!=EOF)
  fputc(ch,fp2);

fclose(fp1);
fclose(fp2);
}

字串讀寫函式 fgets, fputs

一、讀字串函式fgets

fgets(字元陣列名,n,檔案指標); 

其中

n是一個正整數, 表示從檔案中讀出的字串不超過 n-1個字元。在讀入的最後一個字元後加上串結束標誌 '\0' 

說明:

1. 在讀出n-1個字元之前,如遇到了換行符或EOF,則結束。 // 串結束符 呢 ?

2. fgets函式也有返回值,其返回值是字元陣列的首地址。

二、寫字串函式fputs

fputs(字串,檔案指標

其中 字串可以是字串常量,字元陣列名,指標變數。

例如:

向一檔案寫入一串,然後讀取前10字元。

#include <stdio.h>

main()
{
FILE *fp;
char str[128]="0123456789";
char ch;

if((fp=fopen("str","wt+"))==NULL)
{
printf("開啟檔案失敗!");
// getch();
exit(1);
}

printf("請輸入一串:");
scanf("%12s",str); // receive 12 chars, and storage 0 behind!
// scanf("%12s", tr); // receive rest chars in istream!

puts(str);
fputs(str,fp);

rewind(fp);

fgets(str, 11, fp); // read at most 10 chars, and storage 0 behind!
puts(str);

fclose(fp);
}

/*
請輸入一串:01234567891011
012345678910
0123456789
Press any key to continue
*/


資料塊讀寫函式 fread, fwrite

  可用來讀寫一組資料,如陣列,結構等塊資料。

fread(buffer,size,count,fp); 

fwrite(buffer,size,count,fp); 

其中

buffer是一個指標,表示存放資料塊的首地址。

size 表示資料塊的位元組數。

count 表示要讀寫的資料塊塊數。

fp 表示檔案指標。

例如:

fread(fa,4,5,fp); 其意義是從fp所指的檔案中,每次讀4個位元組(一個實數)送入實陣列fa中,連續讀5次,即讀5個實數到fa中。

例如:

從鍵盤輸入兩個學生資料,寫入一個檔案中, 再讀出這兩個學生的資料顯示在螢幕上。

// 注意: scanf("%s%d", str, &iv); 輸入串時不能有空格! 如果允許空格,使用gets。

#include<stdio.h>

struct stu
{
char name[10];
int num;
int age;
char addr[15];
}boya[2],boyb[2],*pp,*qq;

main()
{
FILE *fp;
char ch;
int i;

pp=boya;
qq=boyb;
if((fp=fopen("stu_list","wb+"))==NULL)
{
printf("Cannot open file strike any key exit!");
// getch();
exit(1);
}

printf("\ninput data\n");

for(i=0;i<2;i++,pp++)
scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);

pp=boya;
fwrite(pp,sizeof(struct stu),2,fp);

rewind(fp);

fread(qq,sizeof(struct stu),2,fp);
printf("\n\nname\tnumber age addr\n");


for(i=0;i<2;i++,qq++)
printf("%s\t%5d%7d%s\n",qq->name,qq->num,qq->age,qq->addr);

fclose(fp);
}


格式化讀寫函式fscanffprintf

與前面使用的scanfprintf 函式的功能相似,都是格式化讀寫函式。區別在於 fscanf 函式和fprintf函式的讀寫物件不是鍵盤和顯示器,而是磁碟檔案。

格式: 

fscanf(檔案指標,格式字串,輸入表列); 

fprintf(檔案指標,格式字串,輸出表列); 

例如:

fscanf(fp,"%d%s",&i,s);

fprintf(fp,"%d%c",j,ch);

fscanffprintf函式也可以實現前面的操作。

格式化讀寫的問題: 串中不能有空格!

例如:

#include<stdio.h>

struct stu
{
char name[10];
int num;
int age;
char addr[15];
}boya[2], *pp;

main()
{
FILE *fp;
char ch;
int i;

if((fp=fopen("stu_list","wa+"))==NULL)
{
printf("Cannot open file strike any key exit!");
exit(1);
}

pp=boya;
for(i=0;i<2;i++,pp++)
{
printf(" student %d/2 \n", i);
scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);
fprintf(fp,"%s %d %d %s\n",pp->name,pp->num,pp->age,pp->addr);
printf("%s %d %d %s\n",pp->name,pp->num,pp->age,pp->addr);
}

rewind(fp);
pp = boya;
for(i=0;i<2;i++,pp++)
{
printf(" student %d/2 \n", i);
fscanf(fp, "%s %d %d %s",pp->name,&pp->num,&pp->age,pp->addr);
printf("%s %d %d %s\n",pp->name,pp->num,pp->age,pp->addr);
}

fclose(fp);
}


檔案的隨機讀寫

  前面介紹的是順序讀寫, 即讀寫檔案只能從頭開始,順序讀寫各個資料。 但在實際問題中常要求只讀寫檔案中某一指定的部分。 這就需要移動位置指標,也稱檔案的定位。檔案定位函式主要有兩個 rewind 函式和fseek函式。// 還有ftell 

rewind函式

把檔案內部的位置指標移到檔案首。 

rewind(檔案指標); 

fseek函式

移動檔案內部位置指標

fseek(檔案指標,位移量,起始點); 

其中

"檔案指標"指向被移動的檔案。 

"位移量"表示移動的位元組數,要求位移量是long型資料,以便在檔案長度大於64KB // ? 超過了怎麼辦 )時不會出錯。當用常量表示位移量時,要求加字尾"L"

"起始點"表示從何處開始計算位移量,起始點有三種:檔案首,當前位置和檔案尾。

起始點    符號    值

────────────────────

檔案首      SEEK—SET  0

當前位置    SEEK—CUR  1

檔案末尾   SEEK—END  2

例如:

把位置指標移到離檔案首100個位元組處。

fseek(fp,100L,0);

說明

fseek函式一般用於二進位制檔案。在文字檔案中由於要進行轉換,故往往計算的位置會出現錯誤。

檔案的隨機讀寫在移動位置指標之後,可用前面介紹的任一種讀寫函式進行讀寫。一般是用freadfwrite讀寫一個數據據塊。

例如:

前面的例子中輸出檔案中儲存了3個學生成績,讀出第2個學生的資訊,並修改它。

...

檔案檢測函式

一、檔案結束檢測函式 feof

feof(檔案指標)

判斷檔案是否處於檔案結束位置,如檔案結束,則返回值為1,否則為0

二、讀寫檔案出錯檢測函式 ferror

ferror(檔案指標)

檢查檔案在用各種輸入輸出函式進行讀寫時是否出錯。 如ferror返回值為0表示未出錯,否則表示有錯。

三、檔案出錯標誌和檔案結束標誌置0函式 clearerr

clearerr(檔案指標);

清除出錯標誌和檔案結束標誌。

本章小結

1. C系統把檔案當作一個"",按位元組進行處理。

2. C檔案按編碼方式分為二進位制檔案和ASCII檔案。

3. C語言中,用檔案指標標識檔案,當一個檔案被 開啟時, 可取得該檔案指標。

4. 檔案在讀寫之前必須開啟,讀寫結束必須關閉。

5. 檔案可按只讀、只寫、讀寫、追加四種操作方式開啟,同時還必須指定檔案的型別是二進位制檔案還是文字檔案。

6. 檔案可按位元組,字串,資料塊為單位讀寫,檔案也可按指定的格式進行讀寫。

7. 檔案內部的位置指標可指示當前的讀寫位置,移動該指標可以對檔案實現隨機讀寫。

轉載於:http://blog.chinaunix.net/uid-24118190-id-75229.html