文件的分类
1、在程序设计中,主要用到两种文件:程序文件和数据文件。程序文件里存储的是代码,数据文件里存储的是输入与输出的数据。文件名有唯一的标识:文件路径,文件名,文件后缀。(QQ程序和个人用户文件)
2、二进制文件和ascii文件,再缓冲区里的文件是哪一种?
文件指针
文件存放在内存里的一段连续空间,如何访问?首指针,也就是文件存放的位置。除了文件的位置,文件还包括名称,打开关闭状态,读写属性等该如何表示?结构体。文件当前位置、文件的名字、文件的状态等存放文件的信息使用结构体来表示,结构体类型的名字系统定义为FILE,在stdio.h文件中:
#ifndef _FILE_DEFINED
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag; //文件状态标志
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
不同的编译器FILE包含的内容不同。既然文件使用结构体定义,可以借用上一章结构体的知识来理解定义文件结构变量即具体出一个文件。使用FILE f1定义文件类型的变量f1,f1用来存放一个文件的有关信息。在访问文件时,一般设定指向文件的指针变量,通过该变量访问某一个文件(文件变量)的各种信息,如果有n个文件,则需要设置n个指针变量:
FILE *fp;
文件打开和关闭
fopen()函数实现打开文件,f表示file文件,open打开,调用方式是fopen(文件名,使用文件方式),例如fopen("niu.txt","r"),文件名是niu.txt,打开方式是r,表示read,打开文件从该文件中读数据。如果该文件存在,那么fopen函数读取成功后会将该文件的头(起始地址)作为返回值返回过来,但是如果该文件不存在或者已经损坏,那么fopen会返回一个NULL空指针,例如下面程序:
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *fp;
fp=fopen("a.txt","r");
if(fp==NULL){
printf("can not open file a.txt
");
exit(0);
}
else printf("ye,success!
");
return 0;
}
使用fopen打开名为a.txt的文件,若程序所在目录没有a.txt文件,则输出结果为“can not open file a.txt”,若a.txt文件存在则提示打开成功了,注意这个打开并不是我们人眼看到的弹出一个打开的文件,fopen函数的打开是程序打开了,程序可以看到人眼看不到。
使用文件方式有多种,只读、只写或者可读可写,具体参见课本P335表10.1(第四版),可以再将上述程序的r修改w,再试一下~
有打开就有关闭,否则文件一直处于打开状态,数据容易丢失,关闭文件的函数是fclose(文件指针),注意关闭的参数不是文件名,而是文件指针fp。打开时指针指向该文件,关闭时将fp与文件脱离,文件一直在,只是fp不再指向该文件。fclose函数也有返回值,若关闭成功返回0,否则返回EOF(-1)。
顺序读写数据文件
文件读写库函数(定义在stdio.h)有多种:
1)对文件文件读或者写一个字符的函数是fgetc和fputc,
2)对文本文件读或者写一个字符串的函数是fgets和fputs,
3)对文本文件进行格式化的读或写一个数据的函数是fprintf和fscanf,
4)对文件文件进行读或者写一块数据的函数是fread和fwrite。
重点讲解1),其他三种需要理解含义。
fgetc函数调用方式:
fgetc(fp);
第一个字母f表示文件file,get表示获取/读取,最后一个字母表示字符character,fget含义是从文本文件fp中读取一个字符,读成功则返回所读的字符,失败则返回文件结束标志EOF(-1).
相应的fputc的调用方式是:
fputc(ch,fp);
put写入,fputc将字符ch写入文件指针fp所指向的文件中,写入成功,返回值就是输出的字符,写入失败则返回EOF(-1).
例1:打开(新建)文件a.txt,写入以#结束的字符串,关闭文件。
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *fp;
fp=fopen("a.txt","w");
if(fp==NULL){
printf("can not open file a.txt
");
exit(0);
}
// else printf("ye,success!
"); 打开就可以直接写不需要再提示。
char ch;
//ch='c'; //ch的初始化可固定常量,也可以使用getchar/scanf输入
ch = getchar();
while (ch!='#'){
//scanf("%c",&ch); //scanf可设置格式输入多种类型多个数据,而getchar只能输入字符型,输入时遇到回车键才从缓冲区依次提取字符
fputc(ch,fp);
ch = getchar();
// putchar(ch);
}
fclose(fp);
return 0;
}
根据字符的初始化解释dowhile和while的区别;解释getchar和putchar函数。
例2:打开文件a.txt,读出文件中的内容并打印到终端上。
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *fp;
char ch;
fp=fopen("a.txt","r+");
if(fp==NULL){
printf("can not open file a.txt
");
exit(0);
}
do{
ch=fgetc(fp);
printf("%c",ch);
// }while(ch!=EOF);
}while(!feof(fp)); //feof(fp)用于测试fp所指向的文件的当前状态是否为“文件结束”。如果是,函数则返回的值是1(真),否则为0(假)。
/* while(!feof(fp)){
ch=fgetc(fp);
printf("%c",ch);
}*/
fclose(fp);
return 0;
}
练习:将上述例子中建立的文件a.txt复制到另一个文件中。
向文件读写一个字符串
fgets(str,n,fp):从fp指向的文件读入一个长度为n-1的字符串,并在最后加一个‘ ’字符,然后把这n个字符存放到字符数组str中。读取成功则返回地址str,失败则返回NULL。fgets函数与gets函数类似,只是gets以终端为读取对象,而fgets函数以指定的文件为读取对象。
用格式化的方式读写文件
数据类型丰富,当读取其他类型数据时需要用到格式化方式读写文件。fprintf函数(文件指针,格式化字符串,输出表列),例如:
fprintf(fp,"%d",i);
向文件成块读取数据
fread和fwrite函数:
fread(buffer,size,count,fp);
buffer:是一个地址:对fread来说,它是用来存放从文件读入的数据的存储区的地址;对fwrite来说,是要把此地址开始的存储区中的数据向文件输出
size:要读写的字节数
count:要读写多少个数据项
fp:FILE类型指针