本章我们将介绍 C 程序员如何创建、打开、关闭文本文件或二进制文件。
一个文件,无论它是文本文件还是二进制文件,都是代表了一系列的字节。C 语言不仅提供了访问顶层的函数,也提供了底层(OS)调用来处理存储设备上的文件。本章将讲解文件管理的重要调用。
fseek 可以移动文件指针到指定位置读,或插入写:
int fseek(FILE *stream, long offset, int whence);
seek 设置当前读写点到 offset 处, whence 可以是 SEEK_SET,SEEK_CUR,SEEK_END 这些值决定是从文件头、当前点和文件尾计算偏移量 offset。
你可以定义一个文件指针 FILE *fp,当你打开一个文件时,文件指针指向开头,你要指到多少个字节,只要控制偏移量就好,例如, 相对当前位置往后移动一个字节:fseek(fp,1,SEEK_CUR); 中间的值就是偏移量。 如果你要往前移动一个字节,直接改为负值就可以:fseek(fp,-1,SEEK_CUR)。
执行以下实例前,确保当前目录下 test.txt 文件已创建:
#include <stdio.h>
int main(){
FILE *fp = NULL;
fp = fopen("test.txt", "r+"); // 确保 test.txt 文件已创建
fprintf(fp, "This is testing for fprintf...\n");
fseek(fp, 10, SEEK_SET);
if (fputc(65,fp) == EOF) {
printf("fputc fail");
}
fclose(fp);
}
执行结束后,打开 test.txt 文件:
This is teAting for fprintf...
注意: 只有用 r+ 模式打开文件才能插入内容,w 或 w+ 模式都会清空掉原来文件的内容再来写,a 或 a+ 模式即总会在文件最尾添加内容,哪怕用 fseek() 移动了文件指针位置。
在 Visual Studio 2015 开发环境中运行下列代码, 会提示 fopen 函数不安全:
#include <stdio.h>
int main() {
// 申明文件指针
FILE *filePointer = NULL;
// 以追加模式打开文件 test.txt, 其中路径参数用正斜杠("/")
filePointer = fopen("C:/Users/Administrator/Desktop/test.txt", "a+");
// 在test.txt文件末尾追加写入
fputs("The text was added to the file by executing these codes.", filepointer);
// 关闭文件
fclose(filepointer);
return 0;
}
错误提示:
错误 C4996 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
解决办法,在代码首行写上:
#define _CRT_SECURE_NO_WARNINGS
定义宏忽略警告, 即可忽略安全警告, 生成运行
在新版的 VS 编译环境中提示 fopen 不安全,推荐使用 fopen_s 代替。
fopen_s 和 fopen 的区别在于:
errno_t fopen_s( FILE** pFile, const char *filename, const char *mode );
FILE *fopen(const char *filename, const char *mode)
fopen_s 有三个参数,第一个参数是二级指针,用于存放文件流指针地址,其他的同 fopen 一致。
也就是说,用 fopen 需要这么写:
FILE* fp=NULL;
fp=fopen("\\123.txt","w+");
而如果用 fopen_s:
FILE* fp=NULL;
fopen_s(&fp,"\\123.txt","w+");
就可以了。
对于第一个例子,若是在 Windows 平台上,需要改写成如下代码:
#include <stdio.h>
int main()
{
FILE *fp = NULL;
fp = fopen("C:\\myc\\src\\temp\\test.txt", "w+");
fprintf(fp, "This is testing for fprintf...\n");
fputs("This is testing for fputs...\n", fp);
fclose(fp);
}
经调试通过。
对 fopen()函数补充说明几点:
FILE *fopen( const char * filename, const char * mode );
该函数可能执行失败,返回值是NULL,安全起见必须对返回值进行合法性判断;
该函数有多种模式,其中r+和w+看似一样,都是读写其实还是有几点区别的;
1.模式r+找不到文件不会自动新建,而w+会;
2.模式r+打开文件后,不会清除文件原数据,若直接开始写入,只会从起始位置开始进行覆盖,而w+会直接清零后,再开始读写;
模式的合法性说明:不能用大写,只能是小写,且rb+和r+b都是合法的,但br+和+rb等都是非法的,w和a也是一样的处理;
模式w的自动新建文件是有条件的,只有对应的路径存在(即文件所在的文件夹存在),文件不存在才会新建,否则是不会新建的,返回NULL