1.为什么要使用文件:
因为当我们使用了文件的时候就可以将程序运行时的一些数据从内存中转入到硬盘中,等到我们下次运行程序的时候直接从硬盘中的文件中读取,这样就避免了我们每次运行程序都要重新输入数据的繁琐步骤。所以使用文件对我们来说时非常重要的!
2.什么是文件:
在程序设计中我们一般将文件分成两类(从功能的角度来分类):程序文件,数据文件;
3.文件的打开和关闭:
3.1文件指针:
def:每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名FILE(是一个文件类型).
例如:
vs2013中stdio.h的头文件中对于FILE类型的声明:
struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE;
3.2创建一个文件指针
创建一个名为pf的文件指针:
语法:
FILE* pf;//文件指针变量
3.3文件的打开和关闭:
在文件读写之前我们应先打开文件,文件使用结束之后应该关闭文件;
ANSIC规定使用fopen函数来打开文件,用fclose函数来关闭文件;
3.3.1fopen和fclose函数的声明:
//打开文件 FILE * fopen ( const char * filename, const char * mode ); //关闭文件 int fclose ( FILE * stream );
3.3.2打开方式:
C语言中规定了很多打开方式我们将以表格的方式展示出来
文件使用方式 | 含义 | 如果指定文件不存在 |
“r”(只读) | 为了输入数据打开一个已经存在的文本文件 | 出错 |
“w”(只写) | 为了输出数据,打开一个文本文件 | 建立一个新的文件 |
“a”(追加) | 向文本文件尾添加数据 | 建立一个新的文件 |
“rb”(只读) | 为了输入数据打开一个二进制文件 | 出错 |
“wb”(只写) | 为了输出数据打开一个二进制文件 | 建立一个新的文件 |
“ab”(追加) | 向一个二进制文件尾添加数据 | 出错 |
“r+”(读写) | 为了读和写,打开一个文本文件 | 出错 |
“w+”(读写) | 为了读和写,新建一个新的文件 | 建立一个新的文件 |
“a+”(读写) | 打开一个文件,在文件尾进行读写 | 建立一个新的文件 |
“rb+”(读写) | 为了读和写打开一个二进制文件 | 出错 |
“wb+”(读写) | 为了读和写,新建一个新的二进制文件 | 建立一个新的文件 |
“ab+”(读写) | 打开一个二进制文件,在文件尾进行读和写 | 建立一个新的文件 |
例如:如下代码就是先利用fopen函数用只写的方式打开了一个名为myfile.txt文件然后将该文件指针存储到文件指针变量pFile中,然后用fputs函数将“fopen example”字符串放入到
pFile指针所指向的文件中,然后再用fclose函数来关闭文件;
/* fopen fclose example */ #include <stdio.h> int main () { FILE * pFile; //打开文件 pFile = fopen ("myfile.txt","w"); //文件操作 if (pFile!=NULL) { fputs ("fopen example",pFile); //关闭文件 fclose (pFile); } return 0; }
4.文件的顺序读写
4.1用于顺序读写所需要的函数:
功能 | 函数名 | 适用于 |
字符输入函数 | fgets | 所有输入流 |
字符输出函数 | fputs | 所有输出流 |
文本行输入函数 | fgets | 所有输入流 |
文本行输出函数 | fputs | 所有输出流 |
格式化输入函数 | fscanf | 所有输入流 |
格式化输出函数 | fprintf | 所有输出流 |
二进制输入 | fread | 文件 |
二进制输出 | fwrite | 文件 |
4.2对比一组函数:
scanf/fscanf/sscanf
printf/fprintf/sprintf
例如:(sscanf 和sprintf的例子)
#include <stdio.h> struct S { char name[10]; int age; float score; }; int main() { char buf[100] = {0}; struct S tmp = { 0 }; struct S s = { "zhangsan", 20, 95.5f }; //能够把这个结构体的数据,转换成字符串 //"zhangsan 20 95.5" sprintf(buf, "%s %d %f", s.name, s.age, s.score);//以字符串的形式打印 printf("%s\n", buf); //能否将buf中的字符串,还原成一个结构体数据呢? sscanf(buf, "%s %d %f", tmp.name, &(tmp.age), &(tmp.score)); printf("%s %d %f\n", tmp.name, tmp.age, tmp.score);//以结构的形式打印 return 0; }
5.文件的随机读写
5.1fseek
5.1.1函数声明
int fseek ( FILE * stream, long int offset, int origin );
函数功能:根据文件指针的位置和偏移量来定位文件指针
5.1.2三个origin参数
Constant | Reference position |
SEEK_SET | Beginning of file |
SEEK_CUR | Current position of the file pointer |
SEEK_END | End of file * |
例如:以写二进制文件的方式来打开一个名为example.txt的文件
然后将字符串“This is an apple.”通过文件指针pFile放入到文件中
然后用fseek函数调整文件指针pFile的位置到从文件开始后的第九个字节(bytes)
然后再将字符串“ sam”放入到文件中,最后关闭文件
#include <stdio.h> int main () { FILE * pFile; pFile = fopen ( "example.txt" , "wb" ); fputs ( "This is an apple." , pFile ); fseek ( pFile , 9 , SEEK_SET ); fputs ( " sam" , pFile ); fclose ( pFile ); return 0; }
运行结果:
5.2ftell
返回文件指针相对于起始位置的偏移量
5.2.1函数声明
long int ftell ( FILE * stream );
例如:得到一个文件的长度单位字节
/* ftell example : getting size of a file */ #include <stdio.h> int main () { FILE * pFile; long size; pFile = fopen ("myfile.txt","rb"); if (pFile==NULL) perror ("Error opening file"); else { fseek (pFile, 0, SEEK_END); // non-portable size=ftell (pFile); fclose (pFile); printf ("Size of myfile.txt: %ld bytes.\n",size); } return 0; }
5.3rewind
让文件指针的位置回到文件的起始位置
5.3.1函数声明:
void rewind ( FILE * stream );
例如:
#include <stdio.h> int main () { int n; FILE * pFile; char buffer [27]; pFile = fopen ("myfile.txt","w+"); for ( n='A' ; n<='Z' ; n++) fputc ( n, pFile); rewind (pFile); fread (buffer,1,26,pFile); fclose (pFile); buffer[26]='\0'; puts (buffer); return 0; }
欢迎指正错误!