文件操作是實(shí)際應(yīng)用的重要部分,本文基于C程序設(shè)計(jì)(譚浩強(qiáng)版)所寫。
C語(yǔ)言文件讀寫
fopen,fclose(打開關(guān)閉文件)
FILE *文件指針;// FILE *fp;
fopen(文件名,使用文件方式);//fp = fopen("file","r");
fclose(文件指針);//close(fp);
如果不能打開文件,fopen函數(shù)返回空指針值NULL。可能原因:文件不存在,磁盤故障,磁盤已滿等。
fclose成功執(zhí)行返回0,否則返回EOF(-1)。
文件使用方式 | 含義 | 如果文件不存在 |
---|---|---|
r(只讀) | 輸入,打開文本文件 | 出錯(cuò) |
w(只寫) | 輸出,打開文本文件 | 建立新文件 |
a(追加) | 向文本文件尾添加數(shù)據(jù) | 出錯(cuò) |
rb(只讀) | 輸入,打開二進(jìn)制文件 | 出錯(cuò) |
wb(只寫) | 輸出,打開二進(jìn)制文件 | 建立新文件 |
ab(追加) | 向二進(jìn)制文件尾添加數(shù)據(jù) | 出錯(cuò) |
r+(讀寫) | 讀寫,打開文本文件 | 出錯(cuò) |
w+(讀寫) | 讀寫,建立新的文本文件 | 建立新文件 |
a+(讀寫) | 讀寫,打開文本文件 | 出錯(cuò) |
rb+(讀寫) | 讀寫,打開二進(jìn)制文件 | 出錯(cuò) |
wb+(讀寫) | 讀寫,建立新的二進(jìn)制文件 | 建立新文件 |
ab+(讀寫) | 讀寫,打開二進(jìn)制文件 | 出錯(cuò) |
示例:
File *fp;
//打開
if((fp = fopen("D:\\fp.txt","r"))==NULL)
{
printf("文件打開失敗!");
exit(0);
}
//關(guān)閉
fclose(fp);
順序讀寫文件
fgetc,fputc(讀寫字符)
int fgetc(FILE *stream);//fgetc(fp);
int fputc (char c, File *fp);//fputc("hello",fp);
讀寫成功,返回所讀寫的字符的ASCII碼的十進(jìn)制值。失敗返回EOF(-1)。
返回值是int型,所以應(yīng)該用int ch; ch = fget(fp);
接受讀取到的字符。
fgetc()與getc()/fputc()與putc()作用一樣。
示例:
while(!feof(fp))
{
ch = fgetc(fp);
fputc(ch,fp2);
}
fgets,fputs(讀寫字符串)
char *fgets(char *str, int n, FILE *fp);
int fputs(char *str,FILE *fp);
*str:字符型指針,指向用來存儲(chǔ)所得數(shù)據(jù)的地址。
n:整型數(shù)據(jù),指明存儲(chǔ)數(shù)據(jù)的大小。
*fp:文件結(jié)構(gòu)體指針,將要讀取/寫入的文件流。
fgets成功:返回str數(shù)組首元素的地址;失敗:一開始就遇到文件尾或者讀數(shù)據(jù)出錯(cuò),返回NULL。
fputs成功:返回0;失敗:返回非0值。
fgets實(shí)際上讀入n-1個(gè)字符,然后在最后加一個(gè)'\0',這樣一共是n個(gè)字符,把它們放到字符數(shù)組str中。如果在讀完n-1個(gè)字符前遇到'\n'或者文件結(jié)束符EOF,讀入結(jié)束,但是'\n'也作為一個(gè)字符讀入。
fputs的第一個(gè)參數(shù)可以是字符串常量、字符數(shù)組名或字符型指針。字符串結(jié)尾的'\0'不輸出。
fgets、fputs類似于gets、puts,但是后者以終端為讀寫對(duì)象,前者以特定的文件為讀寫對(duì)象。
示例:
FILE *f1,*f2;
char str[10][10];
int i = 0;
if((f1=fopen("D:\\in.txt","r")) == NULL)
{
printf("can not open the file!");
}
if((f2=fopen("D:\\out.txt","w+")) == NULL)
{
printf("can not open the file!");
}
while(fgets(str[i],10,f1) != NULL)
{
//printf("%d,%s\n",i,str[i]);
fprintf(f2,"%s",str[i]);
i++;
}
fclose(f1);
fclose(f2);
fscanf,fprintf(格式化讀寫文件)
fscanf(文件指針,格式字符串,輸入表列);
fprintf(文件指針,格式字符串,輸出表列);
示例:
fscanf(fp,"%d,%f",&i,&f);
fprintf(fp,"%d,%6.2f",i,f);
類似于scanf,printf。
fscanf,fprintf對(duì)磁盤文件讀寫方便,容易理解。但是輸入是要將文件中的ASCII碼轉(zhuǎn)換成二進(jìn)制形式再保存在內(nèi)存變量中,輸出時(shí)又要將內(nèi)存中的二進(jìn)制形式轉(zhuǎn)換成字符,要花費(fèi)較多時(shí)間。因此,在內(nèi)存與磁盤頻繁交換數(shù)據(jù)的情況下,最好不用fscanf,fprintf。
fread,fwrite(用二進(jìn)制方式讀寫)
fread(buffer,size,count,fp);
fwrite(buffer,size,count,fp);
buffer:地址。對(duì)于fread,是存放從文件讀入數(shù)據(jù)的存儲(chǔ)區(qū)的地址;對(duì)于fwrite,是要把此地址開始的存儲(chǔ)區(qū)中的數(shù)據(jù)向文件輸出。均為起始地址。
size:要讀寫的字節(jié)數(shù)。count:要讀寫多少個(gè)數(shù)據(jù)項(xiàng)(每個(gè)數(shù)據(jù)項(xiàng)長(zhǎng)度為size)。
fp:FILE類型指針。
fread,fwrite函數(shù)的類型為int型,如果函數(shù)執(zhí)行成功,則返回形參count的值,即輸入或輸出數(shù)據(jù)項(xiàng)的個(gè)數(shù)。
示例:
fread(f,4,10,fp);
其中f是一個(gè)float型數(shù)組名(數(shù)組首元素地址)。從fp所指向的文件讀入4個(gè)字節(jié)的數(shù)據(jù),存儲(chǔ)到數(shù)組f中。
struct Student_type
{
char name[10];
int num;
int age;
char addr[30];
}stud[40];
for (i=0;i<40;i++)
{
//每次從fp指向的文件讀入結(jié)構(gòu)體數(shù)組stu的一個(gè)元素
fread(&stud[i],sizeof(struct Student_type),1,fp);
//講內(nèi)存中的學(xué)生數(shù)據(jù)寫入到磁盤文件中去
fwrite(&stud[i],sizeof(struct Student_type),1,fp2);
}
//實(shí)例:向文件中寫入若干結(jié)構(gòu)體數(shù)據(jù)并進(jìn)行讀取。=
#include <iostream>
#include <stdlib.h>
#define SIZE 1
struct Student_type
{
char name[10];
int num;
int age;
char addr[15];
}stud[SIZE];
void save()
{
FILE *fp;
int i;
if((fp=fopen("D:\\stu","wb"))==NULL)
{
printf("err");
exit(0);
}
for(i=0;i<SIZE;i++)
if (fwrite(&stud[i],sizeof(struct Student_type),1,fp)!=1)
{
printf("error");
}
fclose(fp);
}
void read()
{
FILE *fp;
int i;
if((fp=fopen("D:\\stu","rb"))==NULL)
{
printf("err");
exit(0);
}
for(i=0;i<SIZE;i++)
{
if(fread(&stud[i],sizeof(struct Student_type),1,fp)!=1)
{
printf("error");
};
printf("%-10s %4d %4d %-15s\n",stud[i].name,stud[i].num,stud[i].age,stud[i].addr);
}
fclose(fp);
}
int main()
{
int i;
printf("請(qǐng)輸入10組學(xué)生數(shù)據(jù):\n");
for (i=0;i<SIZE;i++)
{
scanf("%s%d%d%s",stud[i].name,&stud[i].num,&stud[i].age,stud[i].addr);
}
save();
read();
system("pause");
return 0;
}
隨機(jī)讀寫文件
rewind
rewind(fp);
使文件位置標(biāo)記指向文件開頭。函數(shù)沒有返回值。
fseek
fseek(文件類型指針,位移量,起始點(diǎn))
起始點(diǎn):用0,1,2代替。0(SEEK_SET):文件開始位置;1(SEEK_CUR):當(dāng)前位置;2(SEEK_END):文件末尾位置。
位移量:以“起始點(diǎn)”為幾點(diǎn),向前移動(dòng)的字節(jié)數(shù)。位移量應(yīng)是long型數(shù)據(jù)(在數(shù)字的末尾加一個(gè)字母L,就表示是long型)。
fseek函數(shù)一般用于二進(jìn)制文件。
示例:
fseek(fp,100L,0);//將文件位置標(biāo)記向前移到離文件開頭100個(gè)字節(jié)處。
fseek(fp,50L,1);//將文件位置標(biāo)記向前移到離當(dāng)前位置50個(gè)字節(jié)處。
fseek(fp,-10L,2);//將文件位置標(biāo)記從文件末尾處向后退10個(gè)字節(jié)。
ftell
ftell(fp);
測(cè)定文件位置標(biāo)記的當(dāng)前位置。用相對(duì)于文件開頭的位移量來表示。
如果調(diào)用函數(shù)時(shí)出錯(cuò),ftell函數(shù)返回值為-1L。
示例:
i = ftell(fp);
if(i==-1L)
{
printf("error");
}
出錯(cuò)檢測(cè)
ferror
ferror(fp);
調(diào)用輸入輸出函數(shù)(fputc,fgetc,fread,fwrite等)時(shí),如果出現(xiàn)錯(cuò)誤,除了函數(shù)返回值有所反映,還可以用ferror檢查。
未出錯(cuò):返回值為0;出錯(cuò):返回非零值。執(zhí)行fopen時(shí),ferror自動(dòng)置0。
clearerr
clearerr(fp);
使文件錯(cuò)誤標(biāo)志和文件結(jié)束標(biāo)志置為0.