上一部分处理了标准输入与输出设备,这部分学习创建、打开、关闭文本文件或二进制文件。
C语言提供了访问顶层的函数,也提供了底层(OS)调用来处理存储设备上的文件。
打开文件
可以使用fopen() 函数来创建一个新的文件或打开一个已有的文件。函数会调用初始化类型 FILE 的一个对象,类型 FILE 包含了所有用来控制流的必要信息。函数原型:FILE *fopen( const char *filename , const char *mode);
- filename 是字符串,用来命名文件
- 访问模式 mode ,处理文本文件:
- r | 打开一个已有文件,允许读写
- w | 打开一个文本文件,允许写入。如果不存在就创建一个,从开头写入内容。如果存在就截断为零长度,重新写入
- a | 打开一个文本文件,追加写入。如果不存在创建,存在追加
- r+ | 打开一个文件,允许读写
- w+ | 打开一个文件,允许读写。如果存在截断为零长度,不存在创建
- a+ | 打开一个文件,允许读写。如果不存在创建。读取会从文件的开头开始,写入只能是追加
- 处理二进制文件
- "rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"
关闭文件
- 使用 fclose() 函数
int fclose( FILE *fp);- 如果成功关闭,fclose()返回零。如果错误返回 EOF。
- 函数会清空缓冲区中的数据,关闭文件,并释放用于该文件的所有内存。EOF是一个定义在头文件 stdion.h 中的常量
写入文件
- 把字符写入流中最简单的函数时 fputc()
int fputc( int c , FILE *fp);- 将参数c的字符写入到fp所指向的输出流中。如果写入成功会返回写入的字符,错误会返回 EOF。
- ` int fputc( const char *s , FILE *fp);
- 将字符串s写入到fp所指向的输出流中。写入成功返回一个非负值,错误返回 EOF。
- 也可以使用 fprintf()函数写入一个字符串
int fprintf(FILE *fp , const char *format, .... )
读取文件
- 读取单个字符最简单的函数 fgetc()
int fgetc( FILE * fp);- 读取一个字符,返回值为读取的字符,错误返回 EOF
- 从流中读取一个字符串
- `char *fgets(char *buf , int n , FILE *fp);
- 从fp指向的输入流中读取 n-1 个字符。读取到的复制到缓冲区 buf ,最后追加一个 null 字符。
- 如果在读取最后一个字符之前遇到换行符 "\n" 或者文件的末尾 EOF ,只返回读取到的字符,包括换行符
- 从流中读取字符串,遇到空格换行停止
int fscanf(FILE *fp , const char *format,...)- 与 fgets 相同,但是遇到第一个空格和换行符时,停止读取
二进制 I/O 函数
size_f fread(void *ptr , size_t size_of_elements,size_t number_of_elements,FILE *a_file);size_f fwrite(const void *ptr , size_t size_of_elements,size_t number_of_elements,FILE *a_file);
下面写一个方法实践一下:
int file_demo()
{
FILE *fp = NULL;
fopen_s(&fp,"tmp/C_test.txt", "w+");
fprintf(fp, "hellp world.\n");
int tes = fputs("the word is hellp;\n",fp);
printf("%d\n", tes);
int ted = fprintf(fp, "hahah,three demo.\n");
printf("%d\n", ted);
int s = 1389;
int tef = fputc(s, fp);
printf("%d\n", tef);
fclose(fp);
}
有几个问题需要注意:
- fopen提示不安全,根据提示可以在开头添加常量忽略不安全提醒,但是失败。改用fopen_s ,文件要求二次指针,因此fp前加&
- fputs 把字符串写入fp指定的流,返回的是非负值
- fputc 把参数c的字符值写入到fp指定流中,写入成功返回写入的字符
下面将方法进行扩充
FILE* rd = NULL;
char buff[255] ;
char buff2[255];
char buff3[255];
fopen_s(&rd, "tmp/C_test.txt", "r");
fscanf_s(rd, " %s ",buff , 20);
printf("读取rd的内容:%s |\n", buff);
//fgetc(rd);
//printf("读取rd内容:%s |\n", buff1);
fgets(buff2, 255, (FILE*)rd);
printf("读取rd内容:%s |\n", buff2);
fgets(buff3, 255, (FILE*)rd);
printf("读取rd内容:%s |\n", buff3);
fclose(rd);
- 主要添加了读取的操作
- 需要注意的是fscanf 需要添加_s 在使用时候需要添加内存大小
防止内存溢出
- 还有一点就是fgetc的使用没有涉及到,也没有找到很对应的测试,暂时搁置。
还有就是 二进制I/O 函数
size_t fread(void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);
size_t fwrite(const void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);
主要用于存储块的读写,通常是数组或结构体