? 第一章 C语言概述
? 第二章 数据类型、运算符与表达式
? 第三章 最简单的 C程序设计
? 第四章 逻辑运算和判断选取控制
? 第五章 循环控制
? 第六章 数组
? 第八章 编译预处理
? 第九章 指针
? 第十章 结构体与共用体
? 第十二章 文件的基本操作
? 第十三章 位运算
§ 12.1 文件的基本概念
文件有多种分类,如,
按文件的内容区分,源程序,图形文件、音频文
件、数据文件等等。
按数据的组织形式分,文本文件、二进制文件
?
C语言可以对文本文件和二进制文件进行读写操作。
§ 12.2 标准 I/O和非标准 I/O
一、标准 I/O(缓冲文件系统 )
每一个文件都会在内存开辟一个“缓冲区”。
缓冲区的作用,临时存放数据,减少对磁盘
的读写次数。
二、系统 I/O(非缓冲文件系统 )
系统不设置缓冲区,由用户设置。
系统 I/O又称为低层文件系统。
? 标准 I/O与 系统 I/O分别采用不同的输入 /输出函数
? 对文件的操作顺序:打开 ?读或写 ?关闭。
三、标准 I/O的读写函数
1,读写一个字符,fgetc( ); fputc( );
2,读写一个字符串,fgets( ); fputs( );
3,格式化读写变量,fscanf( ); fprintf( );
4,格式化读写一个记录 (块 ),fread( ); fwrite( );
§ 12.3 文件类型指针
若要调用文件,系统要求提供以下信息,
? 文件当前的读写位置 ;
? 与文件对应的内存缓冲区地址;
? 缓冲区中未被处理的字符数;
? 文件的操作方式。
对标准 I/O,系统 会在内存为每一个文件开辟
一个, 文件信息区,, 存放上面的信息 。
特别指出,
? 对文件操作所需的“文件信息”是一结构
体变量,且该结构体变量由系统定义
定义形式, typedef struct
{
?
} FILE;
存放文件信息
? 用户只需定义指向文件类型的指针变量即可。
如, FILE *fp1,*fp2;
§ 12.4 文件的打开与关闭
一、文件打开
使用 fopen( )函数。
调用方式, fopen("文件名 ","文件操作方式 ");
返回一个指向该文件的指针或错误标志 NULL。
文件操作方式,
r ? 以只读方式打开一个文本文件
w ? 以只写方式打开一个文本文件
a ? 以追加方式打开一个文本文件
r+ ? 以读 /写方式打开一个文本文件
w+ ? 以读 /写方式建立一个新的文本文件
a+ ? 以读 /写方式打开一个文本文件
rb ? 以只读方式打开一个二进制文件
wb ? 以只写方式打开一个二进制文件
ab ? 以追加方式打开一个二进制文件
rb+ ? 以读 /写方式打开一个二进制文件
wb+ ? 以读 /写方式建立一个新的二进制文件
ab+ ? 以读 /写方式打开一个二进制文件
特别说明, 并不是所有的 C语言系统都具备
以上文件操作方式。
例, #include <stdio.h>
main()
{ FILE *p;
p=fopen("test.txt","r");
if (p==NULL)
{ printf("file open error");
exit(0);
}
printf("file open ok");
}
关注的问题,
? 文件,test.txt”所在位置如何?
? 在程序结束之前并没有关闭被打开的文件,
文件会不会遭到破坏?
? 文件 test.txt的内容是什么?
C语言规定, fopen()函数中的文件名可以是当前
工作目录 (相对路径 )下的也可以是指
定路径 (绝对路径 )下的。
如, fopen("c:\\DOS\\config.sys","r");
二、文件关闭
使用 fclose( )函数
调用方式, fclose(文件指针变量 );
作用,关闭一个已打开的文件 (释放文件信息区 )
提醒,为防止文件数据丢失,文件使用完毕后必
须关闭。 (特别是对以写方式打开的文件 )
三、文件的读写函数
1,文件结尾标志, EOF
从已打开的文件中读一个字符,
fgetc(文件指针变量 )
返回值,字符
注意,文件刚打开时,文件指针指向文件的
开始位置。
注意,
例,设在当前目录下有一个名为 gh.txt的文件,要求编一
程序将该文件中的内容打印在屏幕上。
/*exp15_1.c*/
#include<stdio.h>
main( )
{ FILE *fp;
fp=fopen("gh.txt","r");
char ch;
if (fp= =NULL)
printf("file open error\n");
else
while((ch=fgetc(fp))!=EOF)
putchar(ch);
fclose(fp);
}
注意,gh.txt文件
必须与该程序的
执行文件在同一
目录下。
2,从已打开的文件中读一字符串 (读一行字符 ),
fgets(数组名,n 个字符数,文件指针变量 );
作用,从文件指针所指的文件中读取一行
字符,并将读取的字符放入数组中。
? 读取的字符包括换行符,\n”或文件
结束符,EOF”,若读到文件结束标志,
函数的返回值为 ?1;
? 读取的字符后自动加上字符串结束符
,\0”
? 读到文件尾或出错,则返回 NULL
fgets( )的返回值为数组名,
注意,
例, /* exp15_2.c*/
#include <stdio.h>
main( )
{ FILE *fp;
char w[81];
int k=0;
fp=fopen("file.txt","r");
if(fp=NULL)
printf("file open error\n");
else
{while (fgets(w,80,fp)!=NULL)
{ k=k+1;
printf("%s",w);
}
printf("k=%d",k); }
fclose(fp);
}
把文件 file.txt的内容打印
到屏幕上,并计算该文
件有多少行?
3.按指定格式读取变量
fscanf(文件指针变量,格式控制符字符串,
变量地址表列 );
作用,从文件指针所指的文件中按指定的格式,
读取变量,并将读取的变量保存到对应
的变量中。
例, fscanf(fp,"%s %d %f",name,&n,&p);
有一文件 data.txt的内容如下,
apple 30 4.5
pear 20 3.8
banana 25 2.0
orange 30 2.5
要求将文件的内容按变量的形式取出。
例,/*exp15.3.c*/
#include <stdio.h>
main ( )
{FILE *fp;
char name[20];
int n;
float p;
fp=flpen("data.txt","r");
if (fp= =NULL)
printf("file open errror\n")
else
while (fscanf(fp,"%s %d %f",name,&n,&p)!=EOF)
printf("name=%s\t n=%d\t p=%6.2f\n",name,n,p);
fclose(fp);
}
程序运行结果,
name=apple u=30 p=4.50
name=pear u=20 p=3.80
name=banana u=25 p=2.00
name=orange u=30 p=2.50
? 文件的数据格式要求:每个数据用空格
分开。
? 若文件中的数据无字符串,则数据可
用逗号分开。
若文件中的数据是以逗号“,”分开的,怎
样把每个数据读取到变量中?
注意,
思考,
注意,
4,向文件中写入一个字符
fputc(字符变量,文件指针变量 );
作用,把字符变量的值输出到文件指针变量所
指的文件中。
? 向文件中写入数据时,若文件不存在,
则系统会创建一个新文件。
? 若文件已存在,则
以 "w"方式打开文件时,文件原有内容在
打开的同时会被冲掉。
以 "a"方式打开文件时,文件原有内容保留,
向文件写入的内容插入到文件的尾部。
例,编写一程序,把一字符串写入文件
mytest1.txt中,输入时以字符 !作为结束,
/* exp15_4.c*/
#include <stdio.h>
main( )
{ FILE *fp;
char ch;
fp=fopen("mytest1.txt","w");
if (fp= =NULL)
printf("file open error\n");
else
while ((ch=getchar( ))!='!')
fputc(ch,fp)
}
运行时输入,
结果,查看当前目录下 mytest1.txt文件的内容。
apple 50 5.5
pear 40 4.4
orange 30 3.3
!
5,向文件中写入一个字符串
fputs(数组名,文件指针变量 );
作用,把数组中的内容 (不包括 '\0')输出到文件指
针变量所指的方件中。
#include<stdio.h>
/* exp15_5.c*/
#include<string.h>
main( )
{ FILE *fp;
char w[20];
fp=fopen("mytest2.txt","w");
if(fp= = NULL)
printf(file open error\n");
else
while (strlen(gets(w))>0)
{ fputs(w,fp);
fputs("\n",fp);
} fclose(fp);
}
思考,?若无此
语句, 程序的运
行结果会是怎样
的? ?怎样结束程序的
运行?
运行时输入,
输入的字符串的长度不要超过数组定
义的大小,否则会出错。
apple 50 5.5
pear 40 4.4
orange 30 3.3
注意,
6,按指定的格式向文件输入数据
fprintf(文件指针变量,格式控制符字符串,变量名表列 );
作用,将变量表列中的数据按指定的格式输入到
文件中
如, fprintf(fp,"%d %f %s",a,b,w);
例, /* exp15_6.c*/
#include<stdio.h>
main( )
{FILE *fp;
int a;
float b;
char ch,w[20];
fp=foper("mystest3.txt","w");
if (fp= =NULL)
printf("file open error\n");
else
{ scanf("%s",w);
while(strlen(w)>1
{ scanf("%d %f",&a,&b);
fprintf(fp,"%s%4d%5.1f\n",w,a,b);
scanf("%s",w); }
fclose(fp)
}
运行时输入,
查看当前目录下的 mytest3.txt
apple 50 5.5
pear 40 4.4
orange 30 3.3
任意字母
小结,比较上面三个程序,可以看出,
使用 fgetc( ),fgets( ),fprintf( )可以达到
同一个目的。
§ 12.4 按,记录” 的方式读
写 1,从文件中读,fread(buffer,size,count,fp);
2,向文件中写 a,fwerite(buffer,size,count,fp);
其中,buffer?? 数据存储的起始地址
size ?? 要读写的字节数
count ?? 读写的数据项
fp ?? 文件指针变量
特点,可对数组,结构体数据进行整体输入输出。
返回值, count的值。
注意,使用 fread( ),fwrite未读写文件时,文件必
须以二进制的方式打开。
§ 12.5 文件的随机读写
前面介绍的几种对文件的读写都是顺序读写。
问题的产生, 要求打开文件后,对指定位置
上的数据进行读写操作,减少
一些不心要的中间环节。
解决的办法, 把文件指针移到指定的位置即可。
关键步骤, 文件的定位。
一、文件定位函数
fseek(文件指针变量,位移量、起始点 )
注,? 起始点的取值只有 3种,
? 位移量,以起始点为基点移动的字节数
0 ?? 文件开始处
1 ?? 文件位置指针的当前位置
2 ?? 文件尾。
? ?
文件头 文件尾 起始点
一位移量 十位移量
(往后 ) (往前 ) ?
? 位移量应为 long型
? fseek( )的返回值,
0 ?? 成功
非零 ?? 失败
例,fseek(fp,20l,0);
将位置指针从文件头移动 20个字节
fseek(fp,?10l,1);
将位置指针移到离文件尾 30个字节处
fseek(fp,?30l,2);
将位置从当前位置向后移 10个字节
二、位置函数
ftell(文件指针变量 );
作用,返回位置指针的当前指向
返回值,
≥0,文件指针的当前指向
?1,出错
例, 文件 data1.txt的内容如下,
This is a test,
C语言程序设计,随机读写函数测试。
要求编写一程序随机读出指定的记录。
三、重新定位函数
rewind( 文件指针变量 )
作用,使文件指针返回到文件的开头
无返回值,
/* exp15_7.c*/
#include<stdio.h>
#include<string.h>
main( )
{ FILE *fp;
int loc1,loc2;
long d=8l;
char w;
fp=fopen("data1.txt","r");
if (fp= =NULL)
printf("error\n");
else { loc1=fseek(fp,d,0);
if (loc1= =0) { w=fgetc(fp);
printf("w=%c\n",w);}
}
loc2=ftell(fp);
rewind(fp);
printf("loc2=%d\n",loc2);
loc2=ftell(fp);
fclose(fp);
printf("loc2=%d\n",loc2);
}
运行结果,w=a
loc2=9
loc2=0
思考, 若要采用随机读写的方式读取一个汉字,
程序如何修改?
提示,? 一个汉字占 2个字节
? 可使用 fgets ( )函数将要读出的汉字
装 a数组
? 读取的字符个数必须为 ≥3的单数
四、文件操作的错误检测
C语言对于大多数标准 I/O函数不具有明
确的出错信息。
如, fputc函数,若返回值为 EOF,则有
两种可能,? 文件结束
? 文件出错
如, fgets函数,若返回值为 NULL,则有
两种可能,? 文件结束
? 文件出错
文件操作出错检测函数,ferror
调用形式, ferror(fp)
文件指针
返回值,
0,未出错
非 0:出错
ferror函数的值是最后一次调用时的出
错状态。
注意,
五、文件随机读函数
fread(void *p,int size,int iteams,FILE *fp);
作用, 从 fp所指定的文件中读取 iteams项数
据,放到由 P所指定的块中,每一
项数据的长度为 size字节。
例,P,332-例 9.13
作用,把 P所指定的块中 size个字节长度的内
容作为 iteams项数据写到文件 *fp中去,
fwrite (void *p,int size,int iteams,FILE *fp); 注意,
并不是随机写函数。
§ 12.6 系统 I/O(低级 I/O)
系统 I/O的特点,
·没有文件结构体
·不需定义文件类型指针
·不能读写单个字符、字符串、格式化数据
·只有一种文件读写方法
·主要针对二进制文件
·编程难度大,执行效率高
·缓冲区的大小在程序中设置 (是程序的一部分 )
一、文件打开函数
int open (filename,oflag [,pmode]);
作用,以 aflag的方式打开 filename指定的文件
返回值, 非零整数:成功
?1:不成功
·filename- 可带有路径的文件名,可用字符
串、字符数组名、指向字符串的
指针来表示,
·oflag- 文件的打开方式
O_RDONLY,打开文件用于只读
O_WRONLY,打开文件用于只写
O_RDWR,打开文件用于读写 (对同一个文
件的读写 )
O_APPEND,打开文件准备从文件尾添加,
O_CREAT, 为写而建立一个新文件 (若文
件已存在,此项无效 )
·pmode- 当 oflag为 O_CREAT时,用来规定
对新建文件的许可操作方式
S_IWRITE 只写许可
S_IREAD 只写许可
S_IWRITE|IREAD 读 /写许可
二、读函数
int read (handle,buf,count);
作用:从 handle 所关联的文件中读取 count个字
节的内容,放到用 buf所指定的缓冲区,
·handle- 文件号
·buf - 缓冲区地址
·count - 一次可读入的最大字节数
返回值, 0:已到文件尾
?1:出错
正整数 (读入的字节数 ):成功
四、移动读写指针
long lseek (int handle,long offest,fromwhere);
作用,把 与 handle 相关联的文件指针移到
从 fromwhere 所 指 定 的 位 置 加 上
offset 字节处 。
返回值,
非零值:文件指针相对于文件头
的编移量
?1:出错
fromwhere的取值,
0 —— 文件开始处
1 —— 当前文件指针处
2 —— 文件结尾处
例,从文件 ctlb中第 114个字节开始,读取的 32
个字节
#include<stdio.h>
#include<io.h>
main( )
{ int P;
char buf[32];
P=open("ctlb",O_RDONLY);
if (P = = ?1)
{ printf("file open error");
exit(0);
}
if ((lseek(P,0l,2)<103)
{ printf("length error");
exit (0);
}
lseek (P,103l,0);
read (P,buf,32);
close (P);
}