第 10章 文件本章主要内容,
l 文件,文件系统和文件指针的概念
l 缓冲文件系统文件打开方式
l 缓冲文件系统文件读写函数
l 文件定位与随机读写
l 非缓冲文件系统打开与读写函数
10.1 文件、流和文件系统的概念文件,存储指存储在外部介质上一组相关数据的集合,是操作系统数据管理的单位,
使用数据文件的目的
1、数据文件的改动不引起程序的改动 ——程序与数据分离
2、不同程序可以访问同一数据文件中的数据 ——数据共享
3、能 长期保存 程序运行的中间数据或结果数据
C语言把文件看作一个字节序列,即由一个一个的字节组成,称为? 流 (stream)”,以字节为单位访问,输入输出的数据流的开始和结束仅受程序控制而不受物理符号(如回车换行符)控制。
文件分类
按文件的逻辑结构:
记录文件:由具有一定结构的记录组成(定长和不定长)
流式文件,由一个个字符(字节)数据顺序组成
按存储介质:
普通文件:存储介质文件(磁盘、磁带等)
设备文件,非存储介质(键盘、显示器、打印机等)
按数据的组织形式:
文本文件,ASCII文件,每个字节存放一个字符的 ASCII码
二进制文件,数据按其在内存中的存储形式原样存放如 int型数 10000
0010011100010000
内存存储形式
0010011100010000
二进制形式
0011000100110000001100000011000000110000
ASCII形式文本文件特点,
存储量大、速度慢、便于对字符操作二进制文件特点,
存储量小、速度快、便于存放中间结果
文件处理方法
缓冲文件系统,高级 文件系统,系统自动为正在使用的文件开辟内存缓冲区
非缓冲文件系统,低级文件系统,由用户在程序中为每个文件设定缓冲区磁盘文件输出文件缓冲区输入文件缓冲区程序数据区
a
缓冲文件系统:
缓冲区指令区程序用户数据区 磁盘非缓冲文件系统:
10.2 文件类型指针
文件结构体 FILE
缓冲文件系统为每个正使用的文件在内存开辟文件信息区
文件信息用系统定义的名为 FILE的结构体描述
FILE定义在 stdio.h中
typedef struct
{ int _fd; //文件号
int _cleft; //缓冲区中剩下的字符数
int _mode; //文件操作方式
char *_next; //文件当前读写位置
char *_buff; //文件缓冲区位置
}FILE;
文件类型指针
指针变量说明,FILE *fp1,*fp2 *fp3;
用法:
l文件打开 时,系统 自动 建立文件结构体,并把指向它的指针返回来,程序通过这个指针获得 文件信息,访问文件
l文件关闭 后,它的文件结构体被释放文件名文件使用方式文件类型指针
C程序 操作系统磁盘系统自动地在内存区为每个正在使用的文件名开辟一个缓冲区,为程序中的每一个文件使用,当执行读文件的操作时,从磁盘文件将数据先读入内存
,缓冲区,,装满后再从内存,缓冲区,依此读入接收的变量。执行写文件的操作时,先将数据写入内存,缓冲区,,待内存,缓冲区,装满后再写入文件。
10.3 缓冲文件系统
10.3.1 文件的打开与关闭
C文件操作用 库函数 实现,包含在 stdio.h
文件使用方式,打开文件 -->文件读 /写 -->关闭文件
系统 自动 打开和关闭三个 标准文件,
标准输入 ------键盘 stdin
标准输出 ------显示器 stdout
标准出错输出 -----显示器 stderr
打开文件 fopen
函数形式,fopen(文件名,使用文件方式 )
功能:按指定方式打开文件
返值:正常打开,为指向文件结构体的指针;打开失败,为 NULL
例 文件打开与测试
FILE *fp;
fp=fopen(“aa.c”,“w”);
if(fp==NULL)
{ printf(“File open error!\n”);
exit(0);
}
例 FILE *fp;
fp= fopen (“c:\\fengyi\\bkc\\test.dat”,”r”);
例 FILE *fp;
char *filename=“c:\\fengyi\\bkc\\test.dat”
fp= fopen(filename,”r”);“r+/rb+” (读写 )
“a/ab” (追加 )
“w/wb” (只写 )
“r/rb” (只读 )
“w+/wb+” (读写 )
“a+/ab+” (读写 )
为 输入 打开一个文本 /二进制文件为 输出 打开或建立一个文本 /二进制文件为读 /写打开一个文本 /二进制文件为读 /写建立一个文本 /二进制文件为读 /写打开或建立一个文本 /二进制文件向文本 /二进制文件尾 追加 数据文件使用方式 含义
文件关闭 fclose
作用,使文件指针变量与文件?脱钩?,释放文件结构体和文件指针
函数形式,fclose(文件指针 )
功能:关闭 文件指针 fp指向的文件
返值:正常关闭为 0;出错时,非 0文件打开时返回的文件类型指针磁盘文件输出文件缓冲区输入文件缓冲区程序数据区
a
缓冲文件系统:
fclose
不关闭文件可能会 丢失数据
10.3.2 文件的读写
字符读写函数,fputc与 fgetc
fputc
l函数形式,fputc(fp)
l功能:把一字节代码 c写入文件指针 fp指向的文件中
l返值:正常,返回 c;出错,为 EOF
fgetc
l函数形式,fgetc(fp)
l功能:从 文件指针 fp指向的文件中读取 一字节代码
l返值:正常,返回读到的代码值 ;读到文件尾或出错,为 EOF
文件 I/O与终端 I/O
#define putc(ch,fp) fputc(ch,fp)
#define getc(fp) fgetc(fp)
#define putchar( c ) fputc(c,stdout)
#define getchar( ) fgetc(stdin)
例 文件拷贝例 从键盘输入字符,逐个存到磁盘文件中,直到输入‘ #“为止
#include <stdio.h>
main()
{ FILE *fp;
char ch,*filename=“out.txt”;
if((fp=fopen(filename,"w"))==NULL)
{ printf("cannot open file\n");
exit(0);
}
printf("Please input string:");
ch=getchar();
while(ch!='#')
{ fputc(ch,fp);
putchar(ch);
ch=getchar();
}
fclose(fp);
}
例 读文本文件内容,
并显示
#include <stdio.h>
main()
{ FILE *fp;
char ch,*filename=“out.txt”;
if((fp=fopen(filename,”r"))==NULL)
{ printf("cannot open file\n");
exit(0);
}
while((ch=fgetc(fp))!=EOF)
putchar(ch);
fclose(fp);
}
判断文本文件是否结束
feof
l函数形式,feof(fp)
l功能:判断文件是否结束
l返值:文件结束,返回真(非 0);文件未结束,
返回 0
#include <stdio.h>
main()
{ FILE *in,*out;
char ch,infile[10],outfile[10];
scanf("%s",infile);
scanf("%s",outfile);
if ((in = fopen(infile,"r"))== NULL)
{ printf("Cannot open infile.\n");
exit(0);
}
if ((out = fopen(outfile,"w"))== NULL)
{ printf("Cannot open outfile.\n");
exit(0);
}
while (!feof(in))
fputc(fgetc(in),out);
fclose(in); fclose(out);
}
字符串读写函数,fgets与 fputs
函数 形式,fgets(str,n,fp )
fputs(str,fp)
功能:从 fp指向的文件读 /写一个字符串
返值:
lfgets正常时返回读取字符串的首地址;出错或文件尾,返回
NULL
lfputs正常时返回写入的最后一个字符;出错为 EOF
例 从键盘读入字符串存入文件,再从文件读回显示
fgets从 fp所指文件读 n-1个字符送入 s指向的内存区,
并在最后加一个 ‘ \0’
(若读入 n-1个字符前遇换行符或文件尾( EOF) 即结束 )
fputs把 str指向的字符串写入 fp指向的文件
#include<stdio.h>
main()
{ FILE *fp;
char string[81];
if((fp=fopen("file.txt","w"))==NULL)
{ printf("cann't open file");exit(0); }
while(strlen(gets(string))>0)
{ fputs(string,fp);
fputs("\n",fp);
}
fclose(fp);
if((fp=fopen("file.txt","r"))==NULL)
{ printf("cann't open file");exit(0); }
while(fgets(string,81,fp)!=NULL)
fputs(string,stdout);
fclose(fp);
}
数据块读写函数,fread与 fwrite
函数形式:
fread(buffer,size,count,fp )
fwrite(buffer,size,count,fp )
功能:读 /写数据块
返值:成功,返回读 /写的块数;出错或文件尾,返回 0
格式说明:
lbuffer,指向要输入 /输出数据块的首地址的指针
lsize,每个要读 /写的数据块的大小(字节数)
lcount,要读 /写的数据块的个数
lfp,要读 /写的文件指针
lfread与 fwrite 一般用于 二进制文件 的输入 /输出例 float f[2];
FILE *fp;
fp=fopen(“aa.dat”,“rb”);
fread(f,4,2,fp);
for(i=0;i<2;i++)
fread(&f[i],4,1,fp);
例 struct student
{ int num;
char name[20];
char sex;
int age;
float score[3];
}stud[10];
for(i=0;i<10;i++)
fread(&stud[i],sizeof(struct student),1,fp);
例 从键盘输入 4个学生数据,把他们转存到磁盘文件中去
#include <stdio.h>
#define SIZE 2
struct student_type
{ char name[10];
int num;
int age;
char addr[15];
}stud[SIZE];
main()
{
int i;
for(i=0;i<SIZE;i++)
scanf("%s%d%d%s",stud[i].name,&stud[i].num,
&stud[i].age,stud[i].addr);
save();
display();
}
void save()
{ FILE *fp;
int i;
if((fp=fopen("d:\\fengyi\\exe\\stu_dat","wb"))==NULL)
{ printf("cannot open file\n");
return;
}
for(i=0;i<SIZE;i++)
if(fwrite(&stud[i],sizeof(struct student_type),1,fp)!=1)
printf("file write error\n");
fclose(fp);
}
void display()
{ FILE *fp;
int i;
if((fp=fopen("d:\\fengyi\\exe\\stu_dat","rb"))==NULL)
{ printf("cannot open file\n");
return;
}
for(i=0;i<SIZE;i +)
{ fread(&stud[i],sizeof(struct student_type),1,fp);
printf("%-10s %4d %4d %-15s\n",stud[i].name,
stud[i].num,stud[i].age,stud[i].addr);
}
fclose(fp);
}
格式化读写函数,fprintf与 fscanf
函数形式:
fprintf(fp,format,arg_list )
fscanf(fp,format,arg_list )
功能:按格式对 文件指针 fp指示的文件进行读写操作
返值:成功,返回 I/O的个数 ;出错或文件尾,返回 EOF
例 fprintf(fp,“%d,%6.2f”,i,t); //将 i和 t按 %d,%6.2f格式输出到 fp文件
fscanf(fp,“%d,%f”,&i,&t); //若文件中有 3,4.5,则将 3送入 i,4.5送入 t
例 从键盘按格式输入数据存到磁盘文件中去
#include <stdio.h>
main()
{ char s[80],c[80];
int a,b;
FILE *fp;
if((fp=fopen("test","w"))==NULL)
{ puts("can't open file"); exit() ; }
fscanf(stdin,"%s%d",s,&a);/*read from keaboard*/
fprintf(fp,"%s %d",s,a);/*write to file*/
fclose(fp);
if((fp=fopen("test","r"))==NULL)
{ puts("can't open file"); exit(); }
fscanf(fp,"%s%d",c,&b);/*read from file*/
fprintf(stdout,"%s %d",c,b);/*print to screen*/
fclose(fp);
}
10.3.3 文件的定位
几个概念
文件位置指针 -----指向当前读写位置的指针
读写方式
l顺序读写:位置指针按字节位置顺序移动。
l随机读写:位置指针按需要移动到任意位置。
rewind函数
函数形式,rewind(fp)
功能:重置文件位置指针到文件开头
返值:无例 对一个磁盘文件进行显示和复制两次操作
#include <stdio.h>
main()
{ FILE *fp1,*fp2;
fp1=fopen("d:\\fengyi\\bkc\\ch12_4.c","r");
fp2=fopen("d:\\fengyi\\bkc\\ch12_41.c","w");
while(!feof(fp1)) putchar(getc(fp1));
rewind(fp1);
while(!feof(fp1)) putc(getc(fp1),fp2);
fclose(fp1);
fclose(fp2);
}
fseek函数
函数形式,fseek(fp,offset,origin )
功能:改变文件位置指针的位置
返值:成功,返回 0;失败,返回非 0值文件指针位移量(以起始点为基点,移动的字节数 )
>0 向后移动
<0 向前移动起始点文件开始 SEEK_SET 0
文件当前位置 SEEK_CUR 1
文件末尾 SEEK_END 2
例 fseek(fp,100L,0);
fseek(fp,50L,1);
fseek(fp,-10L,2);
ftell函数
函数形式,ftell(fp)
功能:返回位置指针当前位置 (用相对文件开头的位移量表示 )
返值:成功,返回当前位置指针位置;失败,返回 -1L,
例 磁盘文件上有 3个学生数据,要求读入第 1,3学生数据并显示
main()
{ int i;
FILE *fp;
if((fp=fopen("studat","rb"))==NULL)
{ printf("can't open file\n");exit(0); }
for(i=0;i<3;i+=2)
{ fseek(fp,i*sizeof(struct student_type),0);
fread(&stud[i],sizeof(struct student_type),1,fp);
printf("%s %d %d %s\n",
stud[i].name,stud[i].num,stud[i].age,stud[i].addr);
}
fclose(fp);
}
#include <stdio.h>
struct student_type
{ int num;
char name[10];
int age;
char addr[15];
}stud[3];
#include"stdio.h"
main()
{ FILE *fp;
char filename[80];
long length;
gets(filename);
fp=fopen(filename,"rb");
if(fp==NULL)
printf("file not found!\n");
else
{ fseek(fp,0L,SEEK_END);
length=ftell(fp);
printf("Length of File is %1d bytes\n",length);
fclose(fp);
}
}
例 求文件长度
10.3.4 出错的处理
ferror函数
函数形式,ferror(fp)
功能:测试文件是否出现错误
返值:未出错,0;出错,非 0
说明
l每次调用文件输入输出函数,均产生一个新的 ferror函数值,
所以应及时测试
lfopen打开文件时,ferror函数初值自动置为 0
clearerr函数
函数原型,clearerr(fp)
功能:使文件错误标志置为 0
返值:无
说明:出错后,错误标志一直保留,直到对同一文件调 clearerr(fp)或 rewind或任何其它一个输入输出函数例 ferror()与 clearerr()举例
#include <stdio.h>
int main(void)
{ FILE *stream;
stream = fopen("DUMMY.FIL","w");
getc(stream);
if (ferror(stream))
{ printf("Error reading from DUMMY.FIL\n");
clearerr(stream);
}
if(!ferror(stream))
printf("Error indicator cleared!");
fclose(stream);
return 0;
}
非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快。
由于 ANSI标准不再包括非缓冲文件系统,因此本节的目的只是为了便于读者阅读现存的含低级输入输出函数的 C程序,而不是提倡再用这类函数去开发新的、供使用的 C语言软件。 。
10.4 非缓冲文件系统
10.4.1 文件的打开、建立与关闭打开文件 fopen
函数形式,open(filename,access);
功能:打开名字为 filename的文件,并 access来设置该文件的访问模式。
打开方式 作用
0(O_RDONLY) 只能读
1(O_WRONLY) 只能写
2(O_RDWR) 可以读/写
返值:正常打开,一个正整数,它就是与该文件相联结的文件说明符 ;打开失败,为 -1例如,open("Li_l",0),打开一个名为? LL1”的文件,只能用于输入。
建立文件 creat
函数形式,creat(filename,pmode) ;
功能:建立由 filename指定名字并由 pmode指定访问模式的新文件 。
返值:操作成功,大于或等于 0的文件说明符 ;
打开失败,为 -1
关闭文件 close
函数形式,close(fd) ;
功能:关闭与 fd相联结的文件 。
返值:操作成功时为 0;失败时为 -1
10.4.2 文件的读写读文件 read
函数 形式,read(fd,buf,count)
功能:从 fd说明的文件中读取 count个字节到 buf
所指向的缓冲区 。
l其中 fd为文件号
lbuf是一个地址
返值:执行 read成功,则函数返回实际读入的字节数;若遇文件结束则函数值返回 0;若有错,
返回 -1。
例:从文件 TEST.TST中读取它的前半 100个字节并放到数组 buffer
中,并将该字符串显示出来。
main()
{int fd;
char buffer[100];
if ((fd=open("TEST.TST",0))= =-1) /* 打开文件 * /
{ printf("cannot open file !\n");
exit(0);
}
if(read(fd,buffer,100)!=100) /*判断读写的字节数是否正确
*/
printf("Possible read error.");
printf("%s\n",buffer);
close(fd);
}
写文件 write
函数 形式,write(fd,buf,count)
功能:将 count个字节从 buf写入到 fd说明的文件中。
l其中 fd为文件号
lbuf是一个地址
返值:执行 write成功,则函数返回实际写入的字节数;若写入失败则返回 -1。
例:从终端键盘读入 100个字符,然后输出到磁盘文件,TEST.TST”中 。
main( )
{
int fd;
char buffer[100];
if ((fd=open("TEST.TST",0))= = -1) /* 打开文件 * /
{ printf("cannot open file !\n");
exit(0);
}
gets(buffer);
if(write(fd,buffer,100)! =100)
printf("write error");
close(fd);

随机读写定位函数 lseek
函数 形式,lseek( fd,offset,origin)
功能:来移动文件位置指针到一个指定的位置,
从而实现对非缓冲文件的随机存取。与缓冲文件系统的 fseek()函数相同 。
参数说明:
lfd,文件号,buf是一个地址,它指向程序员指定的“缓冲区”
的开头 文件指针。
lorigin:起始点,它指出以什么位置为基准进行移动,用 0,1和
2来表示。 0,1和 2分别代表“文件开始位置”、文件“当前位置”和“文件末尾”。
loffset:位移量,它指出以,起始点,为基点,向前移动的字节数,位移量是 long型数据。若位移量为负数,则指针回头向后移动。 。
本章结束,谢谢!