1.什么是文件
按照文件的功能来划分,文件可以分为程序文件和数据文件。
数据文件:文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。
程序文件:包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)。
2.文件的打开和关闭
2.1文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名FILE。
在vs2013中FILE定义为:
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
文件指针的定义
FILE* pf;
定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件。
2.2文件的打开和关闭
文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。
使用fopen()打开文件,使用fclose()关闭文件。函数原型为:
FILE *fopen( const char *filename, const char *mode );//第二个参数为打开方式。
int fclose( FILE *stream );
文件的书写函数:
实例1
int main()
{
FILE* pf=fopen("examplefile.txt","w");
if(pf!=NULL)
{
fputs(" This is fopen example ",pf);
fclose(pf);
}
return 0;
}
实例2:实现文件拷贝
int main()
{
//只读文件
FILE*pr=fopen("data.txt","r");
if(pr==NULL)
{
printf("%s\n",strerror(errno));
return 0;
}
//只写文件
FILE*pw=fopen("data2.txt","w");
if(pw==NULL)
{
printf("%s\n",strerror(errno));
flose(pr);
free(pr);
pr=NULL;
return 0;
}
//拷贝文件
int ch=0;
//一次拿一个字符
while((ch=fgetc(pr))!=EOF)
{
fputs(ch,pw);
}
fclose(pw);
free(pw);
pw=NULL;
return 0;
}
对比sscanf/sprintf、scanf/printf与fscanf/fprintf
struct stu{
char name[20];
int age;
double d;
};
int main()
{
struct stu s={"张三",20,90.5};
struct stu tmp={ 0 };
char buf[100]={0};
//将s里面的内容按照一定的格式存储在buf中
sprintf(buf,"%s %d %lf",s.name,s.age,s.d);
printf("%s\n",buf);
//把字符串buf的内容按照一定的格式输入在tmp.name,tmp.age,tnp.d里面去
sscanf(buf,"%s %d %lf",tmp.name,&(tmp.age),&(tmp.d));
printf("%s %d %lf",tmp.name,tmp.age,tmp.d);
}
3.文件的随机读取
3.1 fseek函数
int fseek ( FILE * stream, long int offset, int origin );
根据文件指针的位置和偏移量来定位文件指针。向前偏移为负,向后偏移为正。offset参数代表了偏移量。
fseek(FILE * stream, long int offset,SEE_CUR)//从当前的位置定位文件指针
fseek(FILE * stream, long int offset,SEEK_SET)//从文件开始的位置定位文件指针
fseek(FILE * stream, long int offset,SEEK_END)//从文件结束的地方开始定位文件指针
实例:
#include <stdio.h>
int main ()
{
FILE * pFile;
pFile = fopen ("myfile.txt","wb");
fputs("This is an apple",pFile);
fseek (pFile, 9, SEEK_SET);
fputs(" sam",pFile);
flose(pFile);
return 0;
}
//文本里面的内容为:This is a sample
3.2ftell
long int ftell ( FILE * stream );
返回文件指针相对于起始位置的偏移量
3.3rewind
void rewind ( FILE * stream);
让文件指针的位置回到文件的起始位置
文本文件和二进制文件
根据数据的组织形式,数据文件被称为文本文件或者二进制文件。
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。
int main()
{
int a=10000;
FILE*pf=fopen("test.txt","wb");
fwrite(&a,4,1,pf);
fclose(pf);
pf=NULL;
return 0;
}
//二进制文件为 10 27 00 00
//原因:
//10000的二进制码为00000000000000000010011100010000
//对应的十六进制为 00 00 27 10;vs里面为16进制
//按照小端存储的方式为 10 27 00 00
文件缓冲区
ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。
C语言在不同的地方根据需要使用不同的缓冲区。
缓冲区分为两类:完全缓冲I/O和行缓冲I/O和不带缓冲。
(1)完全缓冲是指的是当前缓冲区被填满时才刷新缓冲区
(2)行缓冲指的是在出现换行时刷新缓冲区。键盘输入通常是行缓冲输入,所以在按下Enter键时才刷新缓冲区。比如getchar()函数。
(3)不带缓冲:标准输出不带缓冲
(4)缓冲区的刷新(执行真正的I/O操作)