https://m.toutiao.com/is/DphVy1X/
C语言中的文件是指一种数据存储形式,它通常用于在磁盘上保存数据。文件可以是文本文件、二进制文件和特殊文件,如设备文件等。
文件基础概念| 什么流
操作系统是以文件为单位对数据进行管理的,输入输出是数据传送的过程,数据如流水一样从一处流向另一处,因此常将输入输出形象地称为流(stream),即输入输出流。C语言把文件看作是一个字节的序列,即由一个一个字节的数据顺序组成。一个输入输出流就是一个字节流或二进制流。
文件基础概念| 文件标识
文件标识包括三部分:
文件基础概念| 文件分类
C语言中的文件可以分为以下几类:
文件基础概念| 文件缓冲区
文件缓冲区是用于暂存文件读写数据的内存空间,即在内存中开辟一段预留的空间,将文件数据先读入该空间中,并在需要时再从该空间中读取或往该空间中写入数据,以减少对磁盘的频繁读写次数。如上文提到的互联网知识所述,使用文件缓冲区可以缓和CPU与I/O设备之间速度不匹配的矛盾。
在C语言中用一个指针变量指向一个文件,这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。C语言内置的文件指针类型FILE*,创建文件基本语法:FILE* pf;
在标准输入输出库库中,系统定义了三个FILE型的指针常量:
一般情况下,在对字符文件进行读写时,文件的位置指针指向文件开头,这时如果对文件进行读的操作,就读第一个字符,然后文件的位置指针顺序向后移一个位置,在下一次执行读的操作时,就将指针指向的第二个字符读入。 依此类推,直到遇文件尾。有时希望在一个文件的原有数据之后再添加新的数据,应该把文件位置指针移到文件尾,然后再接着写入新的数据,这就是文件的追加。注意:这个文件内部的位置指针与C语言中的指针不是一回事。位置指针仅仅是一个标志,表示文件读写到的位置,也就是读写到第几个字节,它不表示地址。文件每读写一次,位置指针就会移动一次,它不需要你在程序中定义和赋值,而是由系统自动设置,对用户是隐藏的。
C语言文件末尾通常是用EOF标识,通常可以通过int feof(FILE* _Stream);判定未见指针是否到达文件末尾,详细使用参见文件读写。
在C语言中,可以使用标准I/O库提供的函数来打开和关闭文件。下面是打开和关闭文件的函数:
FILE* fopen(char const* _FileName,char const* _Mode):用于打开指定的文件,并返回一个文件指针。
int fclose(FILE* _Stream):用于关闭指定的文件,并释放相关资源。
打开方式详解
模式 | 含义 | 说明 |
r | 只读 | 文件必须存在,否则打开失败 |
w | 只写 | 若文件存在,则清除原文件内容后写入;否则,创建文件后写入 |
a | 追加只写 | 若文件存在,则位置指针移到文件末尾,在文件尾部追加写入,故该方式不删除原文件数据;若文件不存在,则创建 |
r+ | 读写 | 文件必须存在。在只读 r 的基础上加 '+’ 表示增加可写的功能。 |
w+ | 读写 | 在只写 w 的基础上加 '+’ 表示增加可读的功能 |
a+ | 读写 | 在”a”模式的基础上,增加可读功能 |
rb | 二进制读 | 功能同模式”r”,区别:b表示以二进制模式打开。下同 |
wb | 二进制写 | 功能同模式“w”。二进制模式 |
ab | 二进制追加 | 功能同模式”a”。二进制模式 |
rb+ | 二进制读写 | 功能同模式”r+”。二进制模式 |
wb+ | 二进制读写 | 功能同模式”w+”。二进制模式 |
ab+ | 二进制读写 | 功能同模式”a+”。二进制模式 |
文件打开常见失败原因
在文件操作总经常会出现文件打开失败问题,总结主要有以下几点原因。
文件打开和关闭综合代码
#include <stdio.h>int main(){ FILE* read = fopen('read.txt', 'r'); if (read == NULL) { printf('r:文件打开失败!\n'); } else { printf('r:文件打开成功!\n'); fclose(read); } FILE* write = fopen('write.txt', 'w'); if (write == NULL) { printf('w:文件打开失败!\n'); } else { printf('w:文件打开成功!\n'); fclose(write); } FILE* append = fopen('append.txt', 'a'); if (append == NULL) { printf('a:文件打开失败!\n'); } else { printf('a:文件打开成功!\n'); fclose(append); } return 0;}
程序运行结果如下:
字符方式读写
字符读写使用下面两个函数完成:
int fputc(int _Character,FILE* _Stream):文件字符写操作
int (FILE* _Stream):文件字符读操作。
案例代码如下:
#include <stdio.h>//保存文件void saveFile(const char* str) { FILE* fp = fopen('info.txt', 'w'); int i = 0; while (str[i] != '\0') { printf('%c\n',fputc(str[i], fp)); i++; } fclose(fp);}//读取文件并显示void readFile() { FILE* fp = fopen('info.txt', 'r'); if (fp == NULL) { printf('文件打开失败!\n'); return; } int userKey = fgetc(fp); while (userKey != EOF) { putchar(userKey); userKey = fgetc(fp); } fclose(fp);}int main(){ char str[] = { 'coolmoying' }; saveFile(str); readFile(); return 0;}
运行结果如下:
字符串方式读写
字符串读写使用下面两个函数完成:
int fputc(int _Character,FILE* _Stream):文件字符写操作
int (FILE* _Stream):文件字符读操作。
案例代码如下:
#include <stdio.h>#include <string.h>#include <stdbool.h>//保存文件void saveFile(const char* str) { FILE* fp = fopen('info.txt', 'w'); //写入多行 fputs(str, fp); fputs(str, fp); fclose(fp);}//读取文件并显示void readFile() { FILE* fp = fopen('info.txt', 'r'); if (fp == NULL) { printf('文件打开失败!\n'); return; } char buffer[1024] = { '' }; while (fgets(buffer, 10, fp)!=NULL) { printf('%s', buffer); } fclose(fp);}int main(){ char str[] = { 'coolmoying\n' }; saveFile(str); readFile(); return 0;}
运行结果如下:
格式化方式读写
格式化读写使用下面两个函数完成:
int fprintf(FILE* _Stream,char const* _Format,…):文件格式化写操作
int fscanf(FILE* _Stream,char const* _Format,…):文件格式化读操作。
通常格式化读写可以用来读写结构体数据,表格数据读写非常方便,案例代码如下:
#include <stdio.h>#include <string.h>struct MM { char name[20]; int age; double money;};//结构体数组写操作void saveFile(struct MM array[], int arrayNum) { FILE* fp = fopen('test.txt', 'w'); for (int i = 0; i < arrayNum; i++) { fprintf(fp, '%s\t%d\t%.1lf\n', array[i].name, array[i].age, array[i].money); } fclose(fp);}//结构体数组读操作void readFile() { FILE* fp = fopen('test.txt', 'r'); struct MM temp; //文件读操作不需要格式控制 while (fscanf(fp, '%s\t%d\t%lf\n', temp.name, &temp.age, &temp.money) != EOF) { //可以存储到数组中,这里直接打印 printf('%s\t%d\t%.1lf\n', temp.name, temp.age, temp.money); } fclose(fp);}int main(){ struct MM array[3] = { {'moying',18,100}, {'girl',28,98}, {'mm',18,78} }; saveFile(array, 3); readFile(); return 0;}
运行结果如下:
二进制方式读写
二进制读写使用下面两个函数完成:
size_t fwrite(void const* _Buffer,size_t* _ElementSize,size_t* _ElementCount,FILE* _Stream):文件格式化写操作
size_t fread(void const* _Buffer,size_t* _ElementSize,size_t* _ElementCount,FILE* _Stream):文件格式化读操作。
通常格式化读写可以用来读写结构体数据非常方便,文件中数据可能存在乱码,能成功读出来即可,读写打开文件方式一定要记得带b走,案例代码如下:
#include <stdio.h>#include <string.h>#include <stdbool.h>struct MM { char name[20]; int age; double money;};//结构体数组写操作void saveFile(struct MM array[], int arrayNum) { FILE* fp = fopen('test.txt', 'wb'); int result=fwrite(array, sizeof(struct MM), arrayNum, fp); fclose(fp);}//结构体数组读操作void readFile() { FILE* fp = fopen('test.txt', 'rb'); struct MM temp = {0}; //通常用返回值作判定,不用数组长度,数据未知 while (fread(&temp, sizeof(struct MM), 1, fp)!=0) { //可以转存到指定数组中,这里只做打印测试 printf('%s\t%d\t%.lf\n', temp.name, temp.age, temp.money); } fclose(fp);}int main(){ struct MM array[3] = { {'moying',18,100}, {'girl',28,98}, {'mm',18,78} }; saveFile(array, 3); readFile(); return 0;}
运行结果如下:
C语言文件指针在文件读写过程中都是内部实现移动过程,一个文件指针写完数据到达文件末尾,直接进行读取操作,不能读出任何东西。C语言提供了一些操作文件指针函数,主要有以下这些:
void rewind(FILE* _Stream):把文件指针还原到文件开头
void fseek(FILE* _Stream,long _Offset,int _Origin):移动文件指针
long fseek(FILE* _Stream):统计文件指针移动字节数
示例程序| 获取文件大小
#include <stdio.h>#include <string.h>#include <stdbool.h>int getFileSize(const char* filename) { FILE* fp = fopen(filename, 'r+'); if (fp == NULL) return 0; fseek(fp, 0L, SEEK_END); int size = ftell(fp); fclose(fp); return size;}int main(){ printf('size:%d\n', getFileSize('./wegame.exe')); return 0;}
运行结果如下:
文件重定向是一种将程序的输入和输出源更改为文件的操作。可以使用重定向操作符 < 和 > 来实现文件重定向。其中 < 运算符用于指定程序的输入数据来源为一个文件,而 > 运算符用于将程序的输出结果写入到一个文件中。重定向操作符后可跟文件路径,表示要将输入或输出流重定向到该文件。C语言提供了以下函数实现文件重定向:
FILE* freopen(char const* _FileName,char const* _Mode,FILE* _Stream):文件重定向
示例程序| 文件重定向
#include <stdio.h>int main() { FILE* ouput = freopen('output.txt', 'w', stdout); //会输出到文件里 puts('coolmoying'); putchar('A'); fprintf(stderr, 'error\n'); //标准错误,不能重定向,只能输出到黑窗口 FILE* input = freopen('input.txt', 'r', stdin); if (!ouput) { perror('重定向失败!\n'); } int a = 0, b = 0; //文件中的数据完成输入 scanf('%d%d', &a, &b); //定向恢复 ouput = freopen('CON', 'w', stdout); if (!ouput) { perror('重定向恢复失败!\n'); } printf('sum=%d\n', a + b); return 0;}
运行结果如下:
联系客服