第十章
本章要点
文件的基本概念
文件的基本函数
文件的顺序读写
文件的随机读写
文件的简单应用
主要内容
10.1 C文件的有关概念
10.2 文件的打开与关闭
10.3 文件的顺序读写
10.4 文件的随机读写
10.5 文件读写的出错检测
§ 10.1 C文件的有关概念
10.1.1什么是文件所谓文件一般指存储在外部介质 (如磁盘磁带 )上数据的集合,
操作系统是以文件为单位对数据进行管理的,
输入输出是数据传送的过程,数据如流水一样从一处流向另一处,因此常将输入输出形象地称为流 (stream),即输入输出流。
C语言把文件看作是一个字符(字节)的序列,
即由一个一个字符(字节)的数据顺序组成。一个输入输出流就是 一 个字节流或二进制流。
§ 10.1 C文件的有关概念
10.1.2 文件名一个文件要有一个惟一的文件标识,以便用户识别和引用。文件标识包括三部分:
(1)文件路径,(2)文件名主干; (3)文件后缀。
文件路径表示文件在外部存储设备中的位置。
如,d,\ cc \ temp \ file1,dat
↑ ↑ ↑
文件路径 文件名主干 文件后缀注意,? 文件标识被称为文件名,但此时的文件名包括以上三部分内容,
而不仅是文件名主干。
文件名主干的命名规则遵循标识符的命名规则。后缀用来表示文件的性质,一般不超过 3个字母,
如,.doc (Word 生成的文件 ),.txt (文本文件 ),.dat (数据文件 )
10.1.3 文件的分类根据数据的组织形式,数据文件可分为ASCII
文件和二进制文件。
ASCII文件 (文本文件 ):每一个字节放一个 ASCII代码二进制文件,把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放,
例,整数 10000在内存中的存储形式以及分别按 ASCII
码形式和二进制形式输出如下图所示:
§ 10.1 C文件的有关概念
§ 10.1 C文件的有关概念
10.1.3 文件的分类
ASCII文件和二进制文件的比较:
ASCII文件 便于对字符进行逐个处理,也便于输出字符。但一般占存储空间较多,而且要花费转换时间。
二进制文件 可以节省外存空间和转换时间,但一个字节并不对应一个字符,不能直接输出字符形式。
一般中间结果数据需要暂时保存在外存上,以后又需要输入内存的,常用二进制文件保存。
§ 10.1 C文件的有关概念
10.1.4 文件缓冲区
ANSI C标准采用,缓冲文件系统,处理文件,
缓冲文件系统,系统自动地在内存区为每一个正在使用的文件开辟一个缓冲区。
从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去。
文件程序数据区输 出 文件缓冲区输 入 文件缓冲区
§ 10.1 C文件的有关概念
10.1.5 文件指针不同的 C编译系统的 FILE类型包含的内容不完全相同,但大同小异。 Turbo C在 stdio.h文件中有以下的文件类型声明:
typedef struct
{ shortlevel; / *缓冲区,满,或,空,的程度 */
unsignedflags; / *文件状态标志 */
charfd; / *文件描述符 */
unsignedcharhold; / *如无缓冲区不读取字符 */
shortbsize; / *缓冲区的大小 */
unsignedchar*buffer;/*数据缓冲区的位置 */
unsignedar*curp;/*指针,当前的指向 */
unsignedistemp;/*临时文件,指示器 */
shorttoken;/*用于有效性检查 */} FILE;
在缓冲文件系统中,每个被使用的文件都要在内存中开辟一
FILE类型的区,存放文件的有关信息,
§ 10.1 C文件的有关概念
10.1.5 文件指针
FILE类型的数组:
FILE f[ 5] ;定义了一个结构体数组 f,它有 5个元素,
可以用来存放 5个文件的信息。
文件型指针变量,
FILE *fp; fp是一个指向 FILE类型结构体的指针变量。可以使 fp指向某一个文件的结构体变量,从而通过该结构体变量中的文件信息能够访问该文件。如果有n个文件,一般应设n个指针变量,使它们分别指向n
个文件,以实现对文件的访问。
§ 10.1 C文件的有关概念
10.1.5 文件指针在标准输入输出库中,系统定义了三个 FILE型的指针变量:
1,stdin (标准输入文件指针 ) 。指向在内存中与键盘相应的文件信息区,因此,用它进行输入就蕴含了从键盘输入。
2.stdout (标准输出文件指针 ) 。指向在内存中与显示器屏幕相应的文件信息区,因此,用它进行输出就蕴含了输出到显示器屏幕。
3.stderr (标准错误文件指针 ),用来输出出错的信息,它也指向在内存中与显示器屏幕相应的文件信息区,因此,在程序运行时的出错的信息就输出到显示器屏幕。
§ 10.1 C文件的有关概念
10.1.6 文件的位置指针位置指针 用来指示当前的读写位置。
一般情况下,在对字符文件进行顺序读写时,文件的位置指针指向文件开头,这时如果对文件进行读的操作,就读第一个字符,然后文件的位置指针顺序向后移一个位置,在下一次执行读的操作时,
就将指针指向的第二个字符读入。依此类推,直到遇文件尾,
↑ ↑ ↑
文件头 读写当前位置 文件尾有时希望在一个文件的原有数据之后再添加新的数据,应该把文件位置指针移到文件尾,然后再接着写入新的数据,这就是文件的 追加 。
§ 10.2 文件的打开与关闭
10.2.1文件的打开 (fopen函数 )
函数调用,
FILE *fp;
fp= fopen( 文件名,使用文件方式 );
①需要打开的文件名,也就是准备访问的文件的名字;
②使用文件的方式(,读,还是,写,等);
③让哪一个指针变量指向被打开的文件。
§ 10.2 文件的打开与关闭
10.2.1 文件的打开 (fopen函数 )
文件使用方式 含 义
,r” (只读 )为 输入 打开一个 文本 文件
,w” (只写 )为 输出 打开一个 文本 文件
,a” (追加 )向 文本 文件尾增加数据
,rb” (只读 )为 输入 打开一个 二进制 文件
,wb” (只写 )为 输出 打开一个 二进制 文件
"ab,(追加 )向 二进制 文件尾增加数据
"r+,(读写 )为 读 /写 打开一个 文本 文件
"w+” (读写 )为 读 /写建立 一个新的 文本 文件
"a+” (读写 )为读 /写打开一个文本文件
"rb+,(读写 )为读 /写打开一个 二进制 文件
,wb+,(读写 )为读 /写 建立 一个新的 二进制 文件
,ab+” (读写 )为读 /写打开一个 二进制 文件
§ 10.2 文件的打开与关闭
10.2.2 文件的关闭 (fclose函数 )
函数调用,
fclose( 文件指针 );
函数功能,
使文件指针变量不指向该文件,也就是文件指针变量与文件,脱钩,,此后不能再通过该指针对原来与其相联系的文件进行读写操作返回值,
关闭成功返回值为0;否则返回 EOF(-1)
§ 10.3 文件的顺序读写
10.3.1 向文件读写一个字符
1.用 fputc函数向文件写入一个字符,调用形式,
fputc ( ch,fp ) ;
函数功能,
将字符( ch的值)输出到 fp所指向的文件中去。
返回值,
如果输出成功,则返回值就是输出的字符;
如果输出失败,则返回一个 EOF.
§ 10.3 文件的顺序读写
10.3.1 向文件读写一个字符
2.fgetc函数从文件读入一个字符,调用形式,
ch=fgetc(fp);
函数功能,
fgetc函数带回一个字符,赋给ch。
返回值,
如果在执行fgetc函数读字符时遇到文件结束符,函数返回一个文件结束标志EOF (即 -1)。
§ 13.4 文件的读写 (续 )
fputc和 fgetc函数使用举例:
例1 3.1 从键盘输入一些字符,逐个把它们送到磁盘上去,直到输入一个,#,为止。
3,读写字符举例例1 0.1从键盘输入一些字符,逐个把它们送到磁盘上去,直到输入一个
“#”为止。
#include <stdlib.h>
#include <stdio.h>
void main(void)
{ FILE *fp;
char ch,filename[10];
scanf("%s",filename);
if((fp=fopen(filename,"w"))==NULL) {
printf("cannot open file\n");
exit(0); /*终止程序 */}
ch=getchar( ); /*接收执行 scanf语句时最后输入的回车符 */
ch=getchar( ); /* 接收输入的第一个字符 */
while(ch!='#'{
fputc(ch,fp);putchar(ch);
ch=getchar(); }
fclose(fp);
}
运行情况如下:
(输入磁盘文件名)
computer and
computer and c (输出一个字符串)
§ 13.4 文件的读写 (续 )
fputc和 fgetc函数使用举例:
例1 3.2 将一个磁盘文件中的信息复制到另一个磁盘文件中 。
例1 0.2将一个磁盘文件中的信息复制到另一个磁盘文件中。
#include <stdlib.h>
#include <stdio.h>
main( )
{FILE *in,*out;
char ch,infile[10],outfile[10];
printf("Enter the infile name:\n");
scanf("%s",infile);
printf("Enter the outfile name:\n");
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);}
运行情况如下:
Enter the infile name
file1,dat (输入原有磁盘文件名
Enter the outfile name:
file2,dat (输入新复制的磁盘文件名)
程序运行结果是将file1,dat文件中的内容复制到
file2,dat中去。
§ 10.3 文件的顺序读写
10.3.2 向文件读写一个字符串
fgets函数函数原形
char *fgets(char *str,int n,FILE *fp);
函数功能,
从指定的文件读入一个字符,
返回值,
若执行fgets函数成功,则返回值为str数组首元素的地址如果一开始就遇到文件尾或读数据出错,则返回
NULL
§ 10.3 文件的顺序读写
10.3.2 向文件读写一个字符串
fputs函数函数原形
int fputs(const str,FILE *fp);
函数功能,
用fputs函数可以向指定的文件输出一个字符串,
§ 13.4 文件的读写 (续 )
fputc和 fgetc函数使用举例:
例1 3.2 将一个磁盘文件中的信息复制到另一个磁盘文件中 。
例1 0.3从键盘读入若干个字符串,对它们按字母顺序排序,
后把它们送到谚磁盘文件中保存,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{ FILE *fp;
char str[3][10],temp[10];
int i,j,k,n=3;
printf("Enter strings:\n");
for(i=0;i<n;i++)
gets(str[i]);
for(i=0;i<n-1;i++) {k=i;
for(j=i+1;j<n;j++)
if(strcmp(str[k],str[j])>0) k=j;
§ 13.4 文件的读写 (续 )
fputc和 fgetc函数使用举例:
例1 3.2 将一个磁盘文件中的信息复制到另一个磁盘文件中 。
if(k!=i)
{strcpy(temp,str[i]);
strcpy(str[k],strcpy(str[i],str[k]);
temp);}
}
if((fp=fopen("D:\\CC\\temp\\string.dat","w"))==NULL) {
printf("can't open file!\n");
exit(0);
}
printf("\nThe new sequence:\n");
for(i=0;i<n;i++)
{fputs(str[i],fp);fputs("\n",fp);
printf("%s\n",str[i]); }
}
运行情况,
Enter strings:
China↙
Canada↙
India↙
The new sequence:
Canada
China
India
§ 10.3 文件的顺序读写
10.3.3 向文件进行格式化读写函数调用,
fprintf ( 文件指针,格式字符串,输出表列);
fscanf ( 文件指针,格式字符串,输入表列);
函数功能,
从磁盘文件中读入或输出字符。
例:
fprintf(fp,”%d,%6.2f”,i,t);
Fscanf (fp,”%d,%f”,&i,&t);
注意:
用 fprintf和 fscanf函数对磁盘文件读写,使用方便,容易理解,
但由于在输入时要将 ASCII码转换为二进制形式,在输出时又要将二进制形式转换成字符,花费时间比较多。因此,在 内存与磁盘频繁交换数据 的情况下,最好不用 fprintf和 fscanf函数,而用 fread和 fwrite函数。
§ 10.3 文件的顺序读写
10.3.4向文件读写一组数据数据块读写函数 (fread()和 fwrite())
函数调用,
fread (buffer,size,count,fp);
fwrite(buffer,size,count,fp);
参数说明:
buffer,是一个指针。
对 fread 来说,它是读入数据的存放地址。
对 fwrite来说,是要输出数据的地址(均指起始地址)。
size,要读写的字节数。
count,要进行读写多少个 size字节的数据项。
fp,文件型指针。
§ 10.3 文件的顺序读写
10.3.4 向文件读写一组数据使用举例:
若 文件以二进制 形式打开:
fread(f,4,2,fp);
此函数从 fp所指向的文件中读入 2个 4个字节的数据,存储到数组 f中。
§ 10.3 文件的顺序读写
10.3.4 向文件读写一组数据使用举例:
若有如下结构类型:
struct student_type
{char name[10];
int num;
int age;
char addr[30];}stud[40];
可以用 fread和 fwrite来进行数据的操作:
for(i=0;i<40;i++)
fread(&stud[ i],sizeof(struct student-type),1,fp);
for(i=0;i<40,i++)
fwrite(&stud[ i],sizeof(struct student-type),1,fp);
§ 10.3 文件的顺序读写
10.3.4 向文件读写一组数据使用举例:
例1 0,4从键盘输入4个学生的有关数据,然后把它们转存到磁盘文件上去。
#include <stdio.h>
#define SIZE 4
struct student_type
{ char name[10];
int num;
int age;
char addr[15];
}stud[SIZE]; /*定义结构 */
§ 13.4 文件的读写 (续 )void save( ){FILE *fp;
int i;
if((fp=fopen("stu-list","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 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( );}/*调用 save()保存学生信息 */
运行情况如下:
输入4个学生的姓名、学号、年龄和地址:
Zhang 1001 19 room -
Fun 1002 20 room -
Tan 1003 21 room -
Ling 1004 21 room -
验证 在磁盘文件,stu -list,中是否已存在此数据,
用以下程序从,stu -list,文件中读入数据,然后在屏幕上输出。
§ 13.4 文件的读写 (续 )
#include <stdio.h>
#define SIZE 4
struct student_type
{ char name[10];
int num;
int age;
char addr[15];
}stud[SIZE];
void main( )
{ int i;
FILE*fp;
fp=fopen("stu-list","rb");
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);}
屏幕上显示出以下信息:
Zhang 1001 19 room -101
Fun 1002 20 room -102
Tan 1003 21 room -103
Ling 1004 21 room -104
如果已有的数据已经以 二进制形式 存储在一个磁盘文件
,stu -dat,中,要求从其中读入数据并输出到
,stu -list,文件中,可以编写一个 load函数,
从磁盘文件中读二进制数据 。
§ 10.3 文件的顺序读写
10.3.4 向文件读写一组数据
void load( )
{FILE *fp;int i;
if((fp=fopen("stu-dat","rb"))==NULL)
{ printf("cannot open infile\n");
return;}
for(i=0;i<SIZE;i++)
if(fread(&stud[i],sizeof(struct student_type),1,fp)!=1)
{if(feof(fp)) {fclose(fp); return;}
printf("file read error\n");}
fclose (fp); }
§ 10.4 文件的随机读写顺序读写和随机读写顺序读写:
位置指针按字节位置顺序移动。
随机读写,
读写完上一个字符(字节)后,并不一定要读写其后续的字符(字节),而可以读些文件中任意位置上所需要的字符(字节)。
10.4.1 文件位置指针的定位
C语言提供以下有关函数使位置指针指向指定的位置,
(1)rewind函数函数功能,
是使位置指针重新返回文件的开头,此函数没有返回值 。
rewind函数函数作用:
使位置指针重新返回文件的开头,无返回值。
应用举例,
例1 3.4 有一个磁盘文件,第一次将它的内容显示在屏幕上,第二次把它复制到另一文件上。
例1 0,5 有一个磁盘文件,第一次将它的内容显示在屏幕上,
第二次把它复制到另一文件上。
#include<stdio.h>
main()
{ FILE *fp1,*fp2;
fp1=fopen("file1.c","r");
fp2=fopen("file2.c","w");
while(!feof(fp1)) putchar(getc(fp1));
rewind(fp1);
while(!feof(fp1))
putc(getc(fp1),fp2);
fclose(fp1);fclose(fp2);
}
(2)fseek函数函数功能:
改变文件的位置指针函数调用形式,
fseek(文件类型指针,位移量,起始点 )
起始点:文件开头 SEEK_SET 0
文件当前位置 SEEK_CUR 1
文件末尾 SEEK_END 2
位移量:以起始点为基点,向前移动的字节数。一般要求为 long型
10.4.1 文件位置指针的定位
fseek函数应用举例,
fseek(fp,100L,0);
将位置指针移到离文件头 100个字节处
fseek(fp,50L,1);
将位置指针移到离当前位置 50个字节处
fseek(fp,50L,2);
将位置指针从文件末尾处向后退10个字节
10.4.1 文件位置指针的定位
(3)ftell函数函数功能:
得到流式文件中的当前位置,用相对于文件开头的位移量来表示。
返回值:
返回当前位置,出错时返回 -1L。
应用举例:
i = ftell(fp);
if(i==-1L) printf(“error\n”);
10.4.1 文件位置指针的定位
rewind函数函数作用:
使位置指针重新返回文件的开头,无返回值。
应用举例,
例1 3.4 有一个磁盘文件,第一次将它的内容显示在屏幕上,第二次把它复制到另一文件上。
例1 0,6在磁盘文件上存有10个学生的数据。要求将第1、3、
5、7、9个学生数据输入计算机,并在屏幕上显示出来。
#include <stdlib.h>
#include<stdio.h>
struct student_type
{ char name[10];
int num;
int age;
char sex;
}stud[10];
10.4.2 随机读写
rewind函数函数作用:
使位置指针重新返回文件的开头,无返回值。
应用举例,
例1 3.4 有一个磁盘文件,第一次将它的内容显示在屏幕上,第二次把它复制到另一文件上。
void main()
{ int i;
FILE *fp;
if((fp=fopen("stud_dat","rb"))==NULL)
{printf("can not open file\n");
exit(0);
}
for(i=0;i<10;i+=2)
{
fseek(fp,i*sizeof(struct student_type),0);
fread(&stud[i],sizeof(struct student_type)
,1,fp);
printf("%s %d %d %c\n",stud[i].name,stud[i].
num,stud[i].age,stud[i].sex);
}
fclose(fp);
}
§ 10.5 文件读写的出错检测
(1)ferror函数调用形式:
ferror(fp);
返回值:
返回 0,表示未出错;返回非 0,表示出错。
在调用一个输入输出函数后立即检查 ferror函数的值,
否则信息会丢失。在执行 fopen函数时,ferror函数的初始值自动置为0。
§ 10.5 文件读写的出错检测
(2)clearerr函数调用形式:
clearerr(fp);
函数作用:
使文件错误标志和文件结束标志置为 0。
只要出现错误标志,就一直保留,直到对同一文件调用 clearerr函数或 rewind函数,或任何其他一个输入输出函数。
本章要点
文件的基本概念
文件的基本函数
文件的顺序读写
文件的随机读写
文件的简单应用
主要内容
10.1 C文件的有关概念
10.2 文件的打开与关闭
10.3 文件的顺序读写
10.4 文件的随机读写
10.5 文件读写的出错检测
§ 10.1 C文件的有关概念
10.1.1什么是文件所谓文件一般指存储在外部介质 (如磁盘磁带 )上数据的集合,
操作系统是以文件为单位对数据进行管理的,
输入输出是数据传送的过程,数据如流水一样从一处流向另一处,因此常将输入输出形象地称为流 (stream),即输入输出流。
C语言把文件看作是一个字符(字节)的序列,
即由一个一个字符(字节)的数据顺序组成。一个输入输出流就是 一 个字节流或二进制流。
§ 10.1 C文件的有关概念
10.1.2 文件名一个文件要有一个惟一的文件标识,以便用户识别和引用。文件标识包括三部分:
(1)文件路径,(2)文件名主干; (3)文件后缀。
文件路径表示文件在外部存储设备中的位置。
如,d,\ cc \ temp \ file1,dat
↑ ↑ ↑
文件路径 文件名主干 文件后缀注意,? 文件标识被称为文件名,但此时的文件名包括以上三部分内容,
而不仅是文件名主干。
文件名主干的命名规则遵循标识符的命名规则。后缀用来表示文件的性质,一般不超过 3个字母,
如,.doc (Word 生成的文件 ),.txt (文本文件 ),.dat (数据文件 )
10.1.3 文件的分类根据数据的组织形式,数据文件可分为ASCII
文件和二进制文件。
ASCII文件 (文本文件 ):每一个字节放一个 ASCII代码二进制文件,把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放,
例,整数 10000在内存中的存储形式以及分别按 ASCII
码形式和二进制形式输出如下图所示:
§ 10.1 C文件的有关概念
§ 10.1 C文件的有关概念
10.1.3 文件的分类
ASCII文件和二进制文件的比较:
ASCII文件 便于对字符进行逐个处理,也便于输出字符。但一般占存储空间较多,而且要花费转换时间。
二进制文件 可以节省外存空间和转换时间,但一个字节并不对应一个字符,不能直接输出字符形式。
一般中间结果数据需要暂时保存在外存上,以后又需要输入内存的,常用二进制文件保存。
§ 10.1 C文件的有关概念
10.1.4 文件缓冲区
ANSI C标准采用,缓冲文件系统,处理文件,
缓冲文件系统,系统自动地在内存区为每一个正在使用的文件开辟一个缓冲区。
从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去。
文件程序数据区输 出 文件缓冲区输 入 文件缓冲区
§ 10.1 C文件的有关概念
10.1.5 文件指针不同的 C编译系统的 FILE类型包含的内容不完全相同,但大同小异。 Turbo C在 stdio.h文件中有以下的文件类型声明:
typedef struct
{ shortlevel; / *缓冲区,满,或,空,的程度 */
unsignedflags; / *文件状态标志 */
charfd; / *文件描述符 */
unsignedcharhold; / *如无缓冲区不读取字符 */
shortbsize; / *缓冲区的大小 */
unsignedchar*buffer;/*数据缓冲区的位置 */
unsignedar*curp;/*指针,当前的指向 */
unsignedistemp;/*临时文件,指示器 */
shorttoken;/*用于有效性检查 */} FILE;
在缓冲文件系统中,每个被使用的文件都要在内存中开辟一
FILE类型的区,存放文件的有关信息,
§ 10.1 C文件的有关概念
10.1.5 文件指针
FILE类型的数组:
FILE f[ 5] ;定义了一个结构体数组 f,它有 5个元素,
可以用来存放 5个文件的信息。
文件型指针变量,
FILE *fp; fp是一个指向 FILE类型结构体的指针变量。可以使 fp指向某一个文件的结构体变量,从而通过该结构体变量中的文件信息能够访问该文件。如果有n个文件,一般应设n个指针变量,使它们分别指向n
个文件,以实现对文件的访问。
§ 10.1 C文件的有关概念
10.1.5 文件指针在标准输入输出库中,系统定义了三个 FILE型的指针变量:
1,stdin (标准输入文件指针 ) 。指向在内存中与键盘相应的文件信息区,因此,用它进行输入就蕴含了从键盘输入。
2.stdout (标准输出文件指针 ) 。指向在内存中与显示器屏幕相应的文件信息区,因此,用它进行输出就蕴含了输出到显示器屏幕。
3.stderr (标准错误文件指针 ),用来输出出错的信息,它也指向在内存中与显示器屏幕相应的文件信息区,因此,在程序运行时的出错的信息就输出到显示器屏幕。
§ 10.1 C文件的有关概念
10.1.6 文件的位置指针位置指针 用来指示当前的读写位置。
一般情况下,在对字符文件进行顺序读写时,文件的位置指针指向文件开头,这时如果对文件进行读的操作,就读第一个字符,然后文件的位置指针顺序向后移一个位置,在下一次执行读的操作时,
就将指针指向的第二个字符读入。依此类推,直到遇文件尾,
↑ ↑ ↑
文件头 读写当前位置 文件尾有时希望在一个文件的原有数据之后再添加新的数据,应该把文件位置指针移到文件尾,然后再接着写入新的数据,这就是文件的 追加 。
§ 10.2 文件的打开与关闭
10.2.1文件的打开 (fopen函数 )
函数调用,
FILE *fp;
fp= fopen( 文件名,使用文件方式 );
①需要打开的文件名,也就是准备访问的文件的名字;
②使用文件的方式(,读,还是,写,等);
③让哪一个指针变量指向被打开的文件。
§ 10.2 文件的打开与关闭
10.2.1 文件的打开 (fopen函数 )
文件使用方式 含 义
,r” (只读 )为 输入 打开一个 文本 文件
,w” (只写 )为 输出 打开一个 文本 文件
,a” (追加 )向 文本 文件尾增加数据
,rb” (只读 )为 输入 打开一个 二进制 文件
,wb” (只写 )为 输出 打开一个 二进制 文件
"ab,(追加 )向 二进制 文件尾增加数据
"r+,(读写 )为 读 /写 打开一个 文本 文件
"w+” (读写 )为 读 /写建立 一个新的 文本 文件
"a+” (读写 )为读 /写打开一个文本文件
"rb+,(读写 )为读 /写打开一个 二进制 文件
,wb+,(读写 )为读 /写 建立 一个新的 二进制 文件
,ab+” (读写 )为读 /写打开一个 二进制 文件
§ 10.2 文件的打开与关闭
10.2.2 文件的关闭 (fclose函数 )
函数调用,
fclose( 文件指针 );
函数功能,
使文件指针变量不指向该文件,也就是文件指针变量与文件,脱钩,,此后不能再通过该指针对原来与其相联系的文件进行读写操作返回值,
关闭成功返回值为0;否则返回 EOF(-1)
§ 10.3 文件的顺序读写
10.3.1 向文件读写一个字符
1.用 fputc函数向文件写入一个字符,调用形式,
fputc ( ch,fp ) ;
函数功能,
将字符( ch的值)输出到 fp所指向的文件中去。
返回值,
如果输出成功,则返回值就是输出的字符;
如果输出失败,则返回一个 EOF.
§ 10.3 文件的顺序读写
10.3.1 向文件读写一个字符
2.fgetc函数从文件读入一个字符,调用形式,
ch=fgetc(fp);
函数功能,
fgetc函数带回一个字符,赋给ch。
返回值,
如果在执行fgetc函数读字符时遇到文件结束符,函数返回一个文件结束标志EOF (即 -1)。
§ 13.4 文件的读写 (续 )
fputc和 fgetc函数使用举例:
例1 3.1 从键盘输入一些字符,逐个把它们送到磁盘上去,直到输入一个,#,为止。
3,读写字符举例例1 0.1从键盘输入一些字符,逐个把它们送到磁盘上去,直到输入一个
“#”为止。
#include <stdlib.h>
#include <stdio.h>
void main(void)
{ FILE *fp;
char ch,filename[10];
scanf("%s",filename);
if((fp=fopen(filename,"w"))==NULL) {
printf("cannot open file\n");
exit(0); /*终止程序 */}
ch=getchar( ); /*接收执行 scanf语句时最后输入的回车符 */
ch=getchar( ); /* 接收输入的第一个字符 */
while(ch!='#'{
fputc(ch,fp);putchar(ch);
ch=getchar(); }
fclose(fp);
}
运行情况如下:
(输入磁盘文件名)
computer and
computer and c (输出一个字符串)
§ 13.4 文件的读写 (续 )
fputc和 fgetc函数使用举例:
例1 3.2 将一个磁盘文件中的信息复制到另一个磁盘文件中 。
例1 0.2将一个磁盘文件中的信息复制到另一个磁盘文件中。
#include <stdlib.h>
#include <stdio.h>
main( )
{FILE *in,*out;
char ch,infile[10],outfile[10];
printf("Enter the infile name:\n");
scanf("%s",infile);
printf("Enter the outfile name:\n");
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);}
运行情况如下:
Enter the infile name
file1,dat (输入原有磁盘文件名
Enter the outfile name:
file2,dat (输入新复制的磁盘文件名)
程序运行结果是将file1,dat文件中的内容复制到
file2,dat中去。
§ 10.3 文件的顺序读写
10.3.2 向文件读写一个字符串
fgets函数函数原形
char *fgets(char *str,int n,FILE *fp);
函数功能,
从指定的文件读入一个字符,
返回值,
若执行fgets函数成功,则返回值为str数组首元素的地址如果一开始就遇到文件尾或读数据出错,则返回
NULL
§ 10.3 文件的顺序读写
10.3.2 向文件读写一个字符串
fputs函数函数原形
int fputs(const str,FILE *fp);
函数功能,
用fputs函数可以向指定的文件输出一个字符串,
§ 13.4 文件的读写 (续 )
fputc和 fgetc函数使用举例:
例1 3.2 将一个磁盘文件中的信息复制到另一个磁盘文件中 。
例1 0.3从键盘读入若干个字符串,对它们按字母顺序排序,
后把它们送到谚磁盘文件中保存,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{ FILE *fp;
char str[3][10],temp[10];
int i,j,k,n=3;
printf("Enter strings:\n");
for(i=0;i<n;i++)
gets(str[i]);
for(i=0;i<n-1;i++) {k=i;
for(j=i+1;j<n;j++)
if(strcmp(str[k],str[j])>0) k=j;
§ 13.4 文件的读写 (续 )
fputc和 fgetc函数使用举例:
例1 3.2 将一个磁盘文件中的信息复制到另一个磁盘文件中 。
if(k!=i)
{strcpy(temp,str[i]);
strcpy(str[k],strcpy(str[i],str[k]);
temp);}
}
if((fp=fopen("D:\\CC\\temp\\string.dat","w"))==NULL) {
printf("can't open file!\n");
exit(0);
}
printf("\nThe new sequence:\n");
for(i=0;i<n;i++)
{fputs(str[i],fp);fputs("\n",fp);
printf("%s\n",str[i]); }
}
运行情况,
Enter strings:
China↙
Canada↙
India↙
The new sequence:
Canada
China
India
§ 10.3 文件的顺序读写
10.3.3 向文件进行格式化读写函数调用,
fprintf ( 文件指针,格式字符串,输出表列);
fscanf ( 文件指针,格式字符串,输入表列);
函数功能,
从磁盘文件中读入或输出字符。
例:
fprintf(fp,”%d,%6.2f”,i,t);
Fscanf (fp,”%d,%f”,&i,&t);
注意:
用 fprintf和 fscanf函数对磁盘文件读写,使用方便,容易理解,
但由于在输入时要将 ASCII码转换为二进制形式,在输出时又要将二进制形式转换成字符,花费时间比较多。因此,在 内存与磁盘频繁交换数据 的情况下,最好不用 fprintf和 fscanf函数,而用 fread和 fwrite函数。
§ 10.3 文件的顺序读写
10.3.4向文件读写一组数据数据块读写函数 (fread()和 fwrite())
函数调用,
fread (buffer,size,count,fp);
fwrite(buffer,size,count,fp);
参数说明:
buffer,是一个指针。
对 fread 来说,它是读入数据的存放地址。
对 fwrite来说,是要输出数据的地址(均指起始地址)。
size,要读写的字节数。
count,要进行读写多少个 size字节的数据项。
fp,文件型指针。
§ 10.3 文件的顺序读写
10.3.4 向文件读写一组数据使用举例:
若 文件以二进制 形式打开:
fread(f,4,2,fp);
此函数从 fp所指向的文件中读入 2个 4个字节的数据,存储到数组 f中。
§ 10.3 文件的顺序读写
10.3.4 向文件读写一组数据使用举例:
若有如下结构类型:
struct student_type
{char name[10];
int num;
int age;
char addr[30];}stud[40];
可以用 fread和 fwrite来进行数据的操作:
for(i=0;i<40;i++)
fread(&stud[ i],sizeof(struct student-type),1,fp);
for(i=0;i<40,i++)
fwrite(&stud[ i],sizeof(struct student-type),1,fp);
§ 10.3 文件的顺序读写
10.3.4 向文件读写一组数据使用举例:
例1 0,4从键盘输入4个学生的有关数据,然后把它们转存到磁盘文件上去。
#include <stdio.h>
#define SIZE 4
struct student_type
{ char name[10];
int num;
int age;
char addr[15];
}stud[SIZE]; /*定义结构 */
§ 13.4 文件的读写 (续 )void save( ){FILE *fp;
int i;
if((fp=fopen("stu-list","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 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( );}/*调用 save()保存学生信息 */
运行情况如下:
输入4个学生的姓名、学号、年龄和地址:
Zhang 1001 19 room -
Fun 1002 20 room -
Tan 1003 21 room -
Ling 1004 21 room -
验证 在磁盘文件,stu -list,中是否已存在此数据,
用以下程序从,stu -list,文件中读入数据,然后在屏幕上输出。
§ 13.4 文件的读写 (续 )
#include <stdio.h>
#define SIZE 4
struct student_type
{ char name[10];
int num;
int age;
char addr[15];
}stud[SIZE];
void main( )
{ int i;
FILE*fp;
fp=fopen("stu-list","rb");
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);}
屏幕上显示出以下信息:
Zhang 1001 19 room -101
Fun 1002 20 room -102
Tan 1003 21 room -103
Ling 1004 21 room -104
如果已有的数据已经以 二进制形式 存储在一个磁盘文件
,stu -dat,中,要求从其中读入数据并输出到
,stu -list,文件中,可以编写一个 load函数,
从磁盘文件中读二进制数据 。
§ 10.3 文件的顺序读写
10.3.4 向文件读写一组数据
void load( )
{FILE *fp;int i;
if((fp=fopen("stu-dat","rb"))==NULL)
{ printf("cannot open infile\n");
return;}
for(i=0;i<SIZE;i++)
if(fread(&stud[i],sizeof(struct student_type),1,fp)!=1)
{if(feof(fp)) {fclose(fp); return;}
printf("file read error\n");}
fclose (fp); }
§ 10.4 文件的随机读写顺序读写和随机读写顺序读写:
位置指针按字节位置顺序移动。
随机读写,
读写完上一个字符(字节)后,并不一定要读写其后续的字符(字节),而可以读些文件中任意位置上所需要的字符(字节)。
10.4.1 文件位置指针的定位
C语言提供以下有关函数使位置指针指向指定的位置,
(1)rewind函数函数功能,
是使位置指针重新返回文件的开头,此函数没有返回值 。
rewind函数函数作用:
使位置指针重新返回文件的开头,无返回值。
应用举例,
例1 3.4 有一个磁盘文件,第一次将它的内容显示在屏幕上,第二次把它复制到另一文件上。
例1 0,5 有一个磁盘文件,第一次将它的内容显示在屏幕上,
第二次把它复制到另一文件上。
#include<stdio.h>
main()
{ FILE *fp1,*fp2;
fp1=fopen("file1.c","r");
fp2=fopen("file2.c","w");
while(!feof(fp1)) putchar(getc(fp1));
rewind(fp1);
while(!feof(fp1))
putc(getc(fp1),fp2);
fclose(fp1);fclose(fp2);
}
(2)fseek函数函数功能:
改变文件的位置指针函数调用形式,
fseek(文件类型指针,位移量,起始点 )
起始点:文件开头 SEEK_SET 0
文件当前位置 SEEK_CUR 1
文件末尾 SEEK_END 2
位移量:以起始点为基点,向前移动的字节数。一般要求为 long型
10.4.1 文件位置指针的定位
fseek函数应用举例,
fseek(fp,100L,0);
将位置指针移到离文件头 100个字节处
fseek(fp,50L,1);
将位置指针移到离当前位置 50个字节处
fseek(fp,50L,2);
将位置指针从文件末尾处向后退10个字节
10.4.1 文件位置指针的定位
(3)ftell函数函数功能:
得到流式文件中的当前位置,用相对于文件开头的位移量来表示。
返回值:
返回当前位置,出错时返回 -1L。
应用举例:
i = ftell(fp);
if(i==-1L) printf(“error\n”);
10.4.1 文件位置指针的定位
rewind函数函数作用:
使位置指针重新返回文件的开头,无返回值。
应用举例,
例1 3.4 有一个磁盘文件,第一次将它的内容显示在屏幕上,第二次把它复制到另一文件上。
例1 0,6在磁盘文件上存有10个学生的数据。要求将第1、3、
5、7、9个学生数据输入计算机,并在屏幕上显示出来。
#include <stdlib.h>
#include<stdio.h>
struct student_type
{ char name[10];
int num;
int age;
char sex;
}stud[10];
10.4.2 随机读写
rewind函数函数作用:
使位置指针重新返回文件的开头,无返回值。
应用举例,
例1 3.4 有一个磁盘文件,第一次将它的内容显示在屏幕上,第二次把它复制到另一文件上。
void main()
{ int i;
FILE *fp;
if((fp=fopen("stud_dat","rb"))==NULL)
{printf("can not open file\n");
exit(0);
}
for(i=0;i<10;i+=2)
{
fseek(fp,i*sizeof(struct student_type),0);
fread(&stud[i],sizeof(struct student_type)
,1,fp);
printf("%s %d %d %c\n",stud[i].name,stud[i].
num,stud[i].age,stud[i].sex);
}
fclose(fp);
}
§ 10.5 文件读写的出错检测
(1)ferror函数调用形式:
ferror(fp);
返回值:
返回 0,表示未出错;返回非 0,表示出错。
在调用一个输入输出函数后立即检查 ferror函数的值,
否则信息会丢失。在执行 fopen函数时,ferror函数的初始值自动置为0。
§ 10.5 文件读写的出错检测
(2)clearerr函数调用形式:
clearerr(fp);
函数作用:
使文件错误标志和文件结束标志置为 0。
只要出现错误标志,就一直保留,直到对同一文件调用 clearerr函数或 rewind函数,或任何其他一个输入输出函数。