C语言文件操作
用户级文件操作
C语言的文件操作也是用户级的文件操作,通过FILE对象来管理每一个被打开的文件,以及提供了用户级文件缓冲区,因此还涉及到冲刷缓冲区等问题
FILE 类
FILE类描述了一个文件流。里面存储了文件控制所需的信息:
- 指向自身缓冲区的的
指针 - 位置指示器
- 状态指示器
所以C语言中对文件的管理就是对FILE对象的管理
基础操作 - 针对一般文件
基础示例
1 |
|
以上代码创建了一个file.txt文件,输入格式化字符串(就和使用printf打印一样)。然后用flcose关闭文件流
fopen 打开文件
fopen能够打开以各种模式磁盘上的文件
FILE* fopen( const char * filename, const char * mode );
返回值:
- 成功时,返回一个不为空的
FILE*指针,用于控制该文件 - 失败时,返回
NULL空指针并设置了全局变量errno
常见模式
| 模式 | 简述 |
| === | === |
| "w" | 创建一个新的空文件用于输出操作。如果已存在同名文件,清除原文件并当作新文件处理 |
| "r" | 只读模式打开文件。且该文件必须存在 |
| "a" | 打开已有文件时,仅用于在文件末尾追加新的内容。并且重定位函数(fseek,fsetpos,reweind)会被忽略,即使成功调用,也没有效果;当文件不存在时,会创建一个新的空文件 |
| “r+“ | 读写模式打开已有文件,不会清除原文件内容,并且读写时均从文件开头开始。打开后第一次操作为写入时,从文件头部开始逐字符覆盖原文件。注读写模式同时只能读或写的一种,第一次取决于先进行哪种操作,可以用fseek函数转换读写模式 |
| “w+“ | 读写模式打开新文件,若存在,则清除原文件内容;读写模式的切换和"r+"模式相同,唯一的区别就是打开时是否清除原文件内容 |
| “a+“ | 从文件末尾打开读写模式,不会清除原文件内容,若打开后第一次操作为写,则从文件末尾开始;若第一次操作为读,则从头开始;读写模式的切换同上 |
二进制模式
如果要以二进制模式打开文件,只需要在上面的模式末尾加上字符b
若有+,则b既可以放在末尾也可以放在中间
r+bw+ba+brb+wb+ab+
强制新建文件
新的C语言标准,C2011(不是C++11),添加了一种新的说明符w,可以被添加在任意"w"后面
"wx""wbx""w+x""w+bx"/"wb+x"
当文件存在时,w会强制fopen函数失败,返回一个NULL空指针
freopen 重定向文件流
FILE* freopen ( const char *filename, const char *mode, FILE * pFile );
- 如果传入了新的文件名(与
pFile控制的文件相比),该函数会关闭pFile原本指向的文件流,并取消关联。然后不论是否成功关闭,freopen会用和fopen同样的方式打开该文件 - 如果文件名还是原文件,则只会改变打开模式
返回值:
- 成功时,返回
pFile内储存的地址 - 失败时,返回
NULL
特别的
freopen用于进程的输入输出重定向会特别有用
1 | freopen ("outfile.txt","w",stdout);//标准输出重定向到文件 |
重定位 文件流位置指示器(stream position indicator)
文件的抽象内存结构
首先我们要明确一下文件的内存结构,如下图

这里及下文用图中的ptr代指标题的中的 文件流位置指示器,这个ptr决定了每一次对文件的读/写操作的起点,同时每一次读/写操作都会使ptr自动往后走,因此要显示控制ptr,就得使用fseek,fsetpos等接口
fseek 重定位
int fseek ( FILE *pFile, long int offset, int origin );
fseek能过直接重定位ptr所指的
参数
pFile:用于控制文件的FILE*类型指针offset:则是偏移量,长整型,表示偏移多少字节origin:该形参标注了偏移量相对于哪个位置计算实际位置
origin有三个宏可以选
| 宏 | 实际位置 |
| SEEK_SET | 偏移量从文件头开始算 |
| SEEK_CUR | 偏移量从当前文件指针ptr(上文介绍的)所在位置开始算 |
| SEEK_END | 偏移量从文件尾开始算 |
返回值
- 成功时,返回
0 - 失败时,返回
非零值,同时,这条语句失效,上文说的ptr没有改变
fgetpos 和 fsetpos 设置 ptr
可以用fgetpos获取ptr的当前位置,并使用输出型参数输出一个fpos_t类型的变量,而fsetpos可以用fpos_t类型的形参设置ptr的当前位置
就好比ptr是当前坐标,每次fgetpos得到一个传送点信息,而fsetpos就可以用这个传送点信息传送ptr过去
示例如下
1 |
|
1 | 第2个字符为: e |
fclose 关闭文件流
可以用fclose显式地关闭文件流
用法为fclose(pFile);
进程正常退出时,也会自动关闭文件流
fprintf 格式化输出字符串
fprintf能格式化输出字符串到指定文件流,除了要指定文件流,格式化字符串的方式和printf一样
- 且
fprintf(stdout,format,...)和printf(format,...)效果一样
fputs 输出字符串
int fputs ( const char * str, FILE * stream );
fputs能将C语言的字符串输入到指定文件流中
fwrite 输出内存数据块
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
ptr是指向内存数据块的指针size是每个数组元素的大小nmemb是元素数量stream是文件流
fwrite可以向指定文件流输入特定大小的内存数据块
1 | int main() |
fscanf 格式化输入
fscanf能像scanf读取标准输入流一样,读取指定文件流
- 且
scanf(stdin,format,...)和printf(format,...)效果一样
fgets 获取一行
char * fgets (char *str, int num, FILE *stream );
行为
fgets会一直读取直到换行符或EOF文件结尾结束读取,但换行符作为非法字符不会被拷贝到形参str中
- 字符串结尾的
\0会被自动添加,且计算在读入的最大字符数 fgets和gets有很大差别,它需要指定最大的读入字符数
形参
str为传入的字符数组作为缓冲区num为拷贝的最大字符数,包括自动添加的结尾\0stream为指定的文件流
返回值
- 成功时,返回
str的值 - 失败时,返回
NULL
示例
1 |
|
1 | get | |