一、文件的打开和关闭
1、文件指针
2、文件打开和关闭
二、文件的顺序读写
1、fgetc()和fputc()函数
2、fgets()和fputs()函数
3、fscanf()和fprintf()函数
4、fread()和fwrite()函数
三、文件的随机读写
1、fseek函数
2、ftell函数
3、fwind函数
一、文件的打开和关闭
1.文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名FILE。
vs2013编译环境提供的stdio.h头文件中有以下文件类型申明:
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。
每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。
一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。下面我们可以创建一个FILE*的指针变量:
FILE* pf;//文件指针变量
定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件。
2、文件打开和关闭
文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。
ANSIC规定使用fopen函数来打开文件,fclose来关闭文件。
FILE* fp=fopen(const char* filename,const char* mode);
//两个参数:打开的文件名和打开方式
fcolse(fp);//关闭文件
(注:上图摘用于bit课件)
实例代码如下:
//int main()
//{
// FILE *p=fopen("C:\\Users\\guan\\Desktop\\test.txt", "w");//文件采用绝对路径和书写的方式进行打开,若采用“w”打开文件则文件若不存在则会新建若存在则会清空
// if (p == NULL)//判断是否打开成功 若没有成功返回相应错误
// {
// printf("%s", strerror(errno));
// return 0;
// }
// fputc('a',p);
// fputc('b', p);
// fputc('c', p);
// fputs("12516513\n", p);
// fputs("scssb\n", p);
// fclose(p);//文件关闭
// p = NULL;//此时指针成为了野指针,需要置零
// return 0;
//}
二、文件的顺序读写
(注:上图摘用于bit课件)
1.fgetc与fputc函数
fgetc()函数是从指定文件中读取一个字符,读取到文件末尾或者读取失败时返回EOF。
fputc()函数则为向文件中写入一个字符。
int fputc(int ch,FLEF* fp);
ch为要写入的字符,fp为文件指针。
且每写入或每读取一个字符,文件指针向后移动一位。
相关例程依旧可参考上边放的代码历程。
2.fgets与fputs函数
fgets()函数用法如下:
char* fgets(char* buf,int n,FILE* fp);
buf为存储字符串的地址,n为读取字符串的长度,fp为文件的指针。
注意!该函数最多只能读取一行,也就是说把n赋值为10000倘若这一行只有一个字节,那么也只会读取一个字节!
fputs()函数用法如下:
int fputs(const char* str,FILE* fp);
相比于fgets,fputs简单很多,即将字符串输入到文件里,str为要输入的字符串,fp为文件指针。
同样的:也是遇到\n停止,写入多行需要重复进行操作!
相应fputs历程依旧可参考上方代码,fgets简易历程如下:
//int main()
//{
// char ch[100] = { 0 };
// FILE *p = fopen("C:\\Users\\guan\\Desktop\\test.txt", "r");
// if (p == NULL)
// {
// printf("%s\n", strerror(errno));
// return 0;
// }
// printf("%c", fgetc(p));
// fgets(ch, 1000, p);
// printf("%s", ch);
// fgets(ch, 1000, p);
// printf("%s", ch);
// return 0;
//}
3.fscanf和fprintf函数
此处先来对比printf与fprintf,scanf与fscanf:
int fprintf( FILE *stream, const char *format, [ argument ]...);//fprintf
int printf( const char *format [, argument]... )//printf
int fscanf ( FILE * stream, const char * format, ... );//fscanf
int scanf ( const char * format, ... );//scanf
printf,是把格式字符串输出到标准输出(一般是屏幕,可以重定向);fprintf, 是把格式字符串输出到指定文件设备中,所以参数笔printf多一个文件指针FILE*。
同样的fscanf是从流中读取数据,并根据参数格式将它们存储到附加参数所指向的位置。附加参数应指向格式字符串中的相应格式说明符指定的类型已分配的对象。
fscanf()和fprintf()函数读写对象不是键盘和显示器,而是磁盘文件。
fprintf历程:
//struct s
//{
// char name[20];
// int age;
// float hight;
//};
//
//int main()
//{
// struct s p1 = { "4516451",123,18885.4 };
// FILE *p = fopen("C:\\Users\\guan\\Desktop\\test.txt", "w");
// if (p == NULL)
// {
// printf("%s", strerror(errno));
// return 0;
// }
// fprintf(p, "%s,%d,%f", p1.name, p1.age, p1.hight);
//
// fclose(p);
// p = NULL;
// return 0;
//}
fscanf历程:
struct S
{
int n;
double d;
};
int main()
{
struct S s = {0};
FILE* pf = fopen("data.txt", "r");//文本文件data.txt
if (NULL == pf)
{
perror("fopen");
return -1;
}
//读文件
fscanf(pf, "%d %lf", &(s.n), &(s.d));
printf("%d %lf\n", s.n, s.d);
//关闭文件
fclose(pf);
pf = NULL;
}
4.fread与fwrite函数
size_t fread(void* buf,size_t size,size_t count,FILE* fp);//fread
size_t fwrite(const void* buf,size_t size,size_t count,FILE* fp);//fwrite
- fread返回实际读取的完整项目数,如果发生错误或在达到计数之前遇到文件结尾,则该值可能小于计数。使用feof或ferror函数区分读取错误和文件结束情况。如果大小或计数为0,则fread返回0且缓冲区内容不变。
- buf为内存区块的指针,用来存放读取到的数据。
- size表示每个数据块的字节数。
- count表示要读取的数据块的个数。
- fp文件指针。
- fwrite返回实际写入的完整项的数量,如果发生错误,该数量可能小于count。buf用来存放要写入的数据,其余参数与fread()相同。
历程如下:
//struct s
//{
// char name[20];
// int age;
// int grade;
//};
//int main()
//{
// FILE* p = fopen("C:\\Users\\guan\\Desktop\\test.txt", "w");
// struct s p1 = { "513",12,13 };
// if (p == NULL)
// {
// printf("%s", strerror(errno));
// return 0;
// }
// fwrite(&p1, sizeof(p1), 1, p);
//
// fclose(p);
// p = NULL;
// return 0;
//}
//
//int main()
//{
// FILE* p = fopen("C:\\Users\\guan\\Desktop\\test.txt", "r");
// struct s p1 = { 0 };
// if (p == NULL)
// {
// printf("%s", strerror(errno));
// return 0;
// }
// fread(&p1, sizeof(p1), 1, p);
// printf("%s,%d,%d", p1.name, p1.grade, p1.age);
// fclose(p);
// p = NULL;
// return 0;
//
//}
三、文件的随机读写
1.fseek函数
int fseek(FILE* stream,long int offset,int origin);
第一个参数为文件指针;第二个参数为偏移量,正数表示向右偏移,负数表示向左偏移;第三个参数设定从文件的哪里开始偏移,可能取值:SEEK_CUR、SEEK_END、SEEK_SET。
- SEEK_SET: 文件开头
- SEEK_GUR: 当前位置
- SEEK_END: 文件结尾
历程如下:
2.ftell函数
long int ftell(FILE* stream);
作用为返回指针相对于起始位置的偏移量,偏倚几个字节返回几个字节。
3.fwind函数
void rewind(FILE* stream);
作用为让指针回到起始位置。