赞
踩
本文主要学习**fopen
,fclose
,fgetc
,fgets
,fputc
,fputs
,fwrite
,fread
,feof
**这几个文件操作函数。
以上函数,需要导入头文件 stdio.h
为什么要学习这些函数?肯定是因为我们需要存储我们的数据,使数据放入到硬盘中方便保存。
本文中梳理一些最常见的文件操作函数。
根据数据的组织形式,数据文件被称为文本文件或者二进制文件。
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件
缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名FILE.
文件指针的创建
FILE* pf
定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件。
fopen
和 fclose
fopen
和fclose
一般是成对出现的,有 fopen
就会有 fclose
fopen
是打开文件的函数,fclose
是关闭文件的函数
//打开文件
FILE * fopen ( const char * filename, const char * mode );
//关闭文件
fclose ( FILE * stream);
fopen
的第一个参数,表示要打开的文件,如果在本目录下,直接书写文件名即可,如果不在本目录,就需要写出文件绝对路径。
fopen
的第二个参数表示对文件的操作形式,可看下图来学习。
fclose
则是关闭我们打开的文件。
在使用完fopen
函数后,最好判断一下, fopen
文件函数是否返回空指针NULL
。
int main() { FILE* pr = fopen("data.txt", "r");//第一个参数是我要打开的文件名,第二个参数代表对文件的操作是“只读” if (NULL == pr)//判断pr是否文件是否打开成功 { printf("open for reading : %s", strerror(errno)); return 0; } FILE* pw = fopen("data2.txt", "w");//第一个参数是我要打开的文件名,第二个参数代表对文件的操作是“写入” if (NULL == pw)//判断文件是否打开成功 { printf("open for writing : %s", strerror(errno)); fclose(pr);//如果打开此文件失败,则关闭上一个文件。 pr = NULL; return 0; } fclose(pr);//文件使用完成后,关闭文件 pr = NULL;//并将文件指针置空 fclose(pw); pw = NULL; return 0; }
fputc
和 fgetc
这两个文件函数在上个案列的代码演示中已经出现, fgetc
是读取文件中的字符, fputc
是将字符输出到文件中。
//fgetc的函数参数
int fgetc( FILE *stream );//stream代表将要读取字符的文件
//fputc的函数参数
int fputc( int c, FILE *stream );// c 代表我们将要存入的字符,stream是我们存放 c 的文件。
这是结合了上一个实例而成的。
#include <stdio.h> #include <string.h> #include <errno.h> int main() { FILE* pr = fopen("data.txt", "r");//第一个参数是我要打开的文件名,第二个参数代表对文件的操作是“只读” if (NULL == pr)//判断pr是否文件是否打开成功 { printf("open for reading : %s", strerror(errno)); return 0; } FILE* pw = fopen("data2.txt", "w");//第一个参数是我要打开的文件名,第二个参数代表对文件的操作是“写入” if (NULL == pw)//判断文件是否打开成功 { printf("open for writing : %s", strerror(errno)); fclose(pr);//如果打开此文件失败,则关闭上一个文件。 pr = NULL; return 0; } int ch = 0; while ((ch = fgetc(pr)) != EOF)//将“data.txt”文件的所有所有内容都写进“data2.txt”这个文件 { fputc(ch, pw); } return 0; }
fgets
和 fputs
fgets
是读取文件中数据的一行,相反,fputs
则是输出一行到文件。
//fgets的函数参数
char *fgets( char *string, int n, FILE *stream );//第一个参数是我们接收文件中数据的字符串,第二个参数 n 表示我们要读取几个字符,不过字符数是 (n-1)个字符,第三个参数则是我们要读取的文件。
//fputs的函数参数
int fputs( const char *string, FILE *stream );//这个函数的参数实际和fgetc差不多,不过这里输出的是字符串到文件stream中,而不是一个字符。
将数据输入到文件中,再次提醒,如果文件不在本目录下,需要加上绝对路径
#include <stdio.h> #include <string.h> #include <errno.h> int main() { FILE* pf = fopen("data.txt", "w"); if (NULL == pf) { printf("open for write : %s", strerror(errno)); return 0; } fputs("hello world\n", pf); fputs("haha\n", pf); fclose(pf); pf = NULL; return 0; }
读取文件
int main() { FILE* pf = fopen("data.txt", "r"); if (NULL == pf) { printf("open for write : %s", strerror(errno)); return 0; } char arr[2] = { 0 };//开辟两个空间来接收数据 fgets(arr, 13, pf);// fgets只能读取(n-1)个字符,所以是13 printf("%s", arr); fgets(arr+1, 5 , pf); printf("%s", arr+1); fclose(pf); pf = NULL; return 0; }
fwrite
和 fread
fwrite
是二进制输出,也就是说,将内容以二进制的形式进行输出到文件中保存。
fread
则是读取文件的以二进制保存的数据。
//fwrite函数参数
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );//第一个参数buffer表示我们要输出的数据的地址,第二参数size是我们要输出的数据大小,第三个参数是count是我们要输入的数据个数,第四个参数则是我们要将数据输入到的文件。
//fread函数参数
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );//第一个参数buffer表示我们要接收的数据的地址,第二参数size是我们要接收的数据大小,第三个参数是count是我们要接收的数据个数,第四个参数则是我们要将数据输入到的buffer的文件。
fwrite
二进制输出
#include <stdio.h> #include <errno.h> #include <string.h> struct Stu { int age; char name[10]; char id[20]; }; int main() { struct Stu s[2] = { { 12, "zhangsan", "253534123" }, {13,"lisi","342342354"}}; FILE* pr = fopen("date.txt", "wb");//wb表示:为了输出数据,打开一个二进制文件 if (NULL == pr) { printf("open for writing : %s", strerror(errno)); } fwrite(&s, sizeof(struct Stu), 2, pr); fclose(pr); pr = NULL; return 0; }
运行后:
使用 fread
读取date.txt
中的数据
#include <stdio.h> #include <errno.h> #include <string.h> struct Stu { int age; char name[10]; char id[20]; }; int main() { struct Stu s[2] = { 0 };//开辟两个相同的结构体数组来接收数据 FILE* pr = fopen("date.txt", "rb"); if (NULL == pr) { printf("open for writing : %s", strerror(errno)); } fread(s, sizeof(struct Stu), 2, pr); printf("%s %d %s\n", s[0].name, s[0].age, s[0].id); printf("%s %d %s\n", s[1].name, s[1].age, s[1].id); fclose(pr); pr = NULL; return 0; }
文件读取成功
feof
应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。
1.文本文件读取是否结束,判断返回值是否为 EOF ( fgetc )
,或者 NULL ( fgets )
例如:
fgetc
判断是否为 EOF
.
fgets
判断返回值是否为 NULL
.
2.二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
fread
判断返回值是否小于实际要读的个数。
文本文件的例子
#include <stdio.h> #include <stdlib.h> int main(void) { int c; // 注意:int,非char,要求处理EOF FILE* fp = fopen("test.txt", "r"); if(!fp) { perror("File opening failed"); return EXIT_FAILURE; } //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环 { putchar(c); } //判断是什么原因结束的 if (ferror(fp)) puts("I/O error when reading"); else if (feof(fp)) puts("End of file reached successfully"); fclose(fp); }
二进制文件的例子
#include <stdio.h> enum { SIZE = 5 }; int main(void) { double a[SIZE] = {1.,2.,3.,4.,5.}; FILE *fp = fopen("test.bin", "wb"); // 必须用二进制模式 fwrite(a, sizeof *a, SIZE, fp); // 写 double 的数组 fclose(fp); double b[SIZE]; fp = fopen("test.bin","rb"); size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 读 double 的数组 if(ret_code == SIZE) { puts("Array read successfully, contents: "); for(int n = 0; n < SIZE; ++n) printf("%f ", b[n]); putchar('\n'); } else { // error handling if (feof(fp)) printf("Error reading test.bin: unexpected end of file\n"); else if (ferror(fp)) { perror("Error reading test.bin"); } } fclose(fp); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。