1、文件存储
文件存取格式
从用户或者操作系统使用的角度(逻辑上)文件可以分为文本文件、二进制文件
文本文件:存储时,是将字符的ascii码值存在磁盘中,取的时候将ascii码翻译成对应的字符,这个翻译器就是文本编辑器
二进制文件:存储的是二进制,取的时候也是二进制
例子
比如,用记事本打开一张图片会出现以下乱码,因为图片的存储编码内容与文本不同,记事本打开的时候就翻译成对应的字符的时候就出了问题
ps:存储文件与大家的软件(翻译器)必须一致才可以进行开发(翻译)
2、磁盘的文件存储
物理上即使磁盘存储的角度,所有文件都是存储的二进制,以字节为单位顺序存储
2、文件指针
当打开一个文件时,操作系统会返回一个结构体.这个结构体有对此文件操作的所有信息
3、相对路径
1、vs中源码执行
相对xxxxxx.vcxproj文件
2、如果是可执行文件exe
则相对于exe所在目录
3、设备文件
程序启动的时候会默认打开三个设备文件获取三个设备文件指针
标准输入文件 stdin(表示键盘)、标准输出文件 stdout(表示显示器)、标准错误文件 stderr(表示显示器)是由系统打开的,可直接使用。
4、文件相关函数
4.1、fopen
函数功能: 打开一个文件
函数原型:FILE * fopen(const char * path,const char * mode);
相关函数:open,fclose,fopen_s[1] ,_wfopen
所需库: <stdio.h>
返回值: 文件顺利打开后,指向该流的文件指针就会被返回。若果文件打开失败则返回NULL,并把错误代码存在errno 中。
一般而言,打开文件后会作一些文件读取或写入的动作,若打开文件失败,接下来的读写动作也无法顺利进行,所以在fopen()后请作错误判断及处理。
打开文件之后,程序可以得到文件的相关信息,例如大小、类型、权限、创建者、更新时间等。在后续读写文件的过程中,程序还可以记录当前读写到了哪个位置,下次可以在此基础上继续操作。
标准输入文件 stdin(表示键盘)、标准输出文件 stdout(表示显示器)、标准错误文件 stderr(表示显示器)是由系统打开的,可直接使用。
阅读:C语言fopen函数的用法,C语言打开文件详解
文件的打开模式见下图
下面例子有点问题(思考)
#include <stdio.h>
#include <stdlib.h>
#define N 100
int main() {
FILE* fp;
char str[N + 1];
//判断文件是否打开失败
if ((fp = fopen("d:\\demo.txt", "rt")) == NULL) {
puts("Fail to open file!");
exit(0);
}
//循环读取文件的每一行数据
while (fgets(str, N, fp) != NULL) {
printf("%s", str);
}
//操作结束后关闭文件
fclose(fp);
return 0;
}
4.2.fflush
fflush() 通常仅用于输出流。它的目的是清除(或刷新)输出buffer,并将缓冲的数据移动到控制台(在stdout的情况下)或磁盘(在文件输出流的情况下)
声明:int fflush(FILE* stream);
参数:stream为文件指针。
返回值:成功返回0,失败返回EOF,错误代码存于errno 中。指定的流没有缓冲区或者只读打开时也返回0值。
fflush()也可用于标准输入(stdin)和标准输出(stdout),用来清空标准输入输出缓冲区。
stdin 是 standard input 的缩写,即标准输入,一般是指键盘;标准输入缓冲区即是用来暂存从键盘输入的内容的缓冲区。stdout 是 standard output 的缩写,即标准输出,一般是指显示器;标准输出缓冲区即是用来暂存将要显示的内容的缓冲区。
另外fclose也可以把缓冲区的内容刷新到磁盘中的功能
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE* fp;
fp = fopen("./demo.txt", "w");
//判断文件是否打开失败
if (fp == NULL) {
perror("打开文件错误:");
exit(0);
}
char buf[12] = "helloworld!";
int i = 0;
while (buf[i] != 0) {
fputc(buf[i],fp);
i++;
};
fflush(fp);//把缓冲区的内容刷新到磁盘中,下次open
fclose(fp);//也可以吧缓冲区的内容刷新到磁盘中
fp = fopen("./demo.txt", "r");
char buff[1024] = "";
i = 0;
//int a = fgetc(fp);
//char b = (char)a;
//char c = fgetc(fp);
while ((buff[i] = fgetc(fp)) != -1) {
i++;
};
printf("%s", buff);
fclose(fp);
return 0;
}
4.3、fclose
声明:int fclose(FILE *stream);
参数:stream为文件流指针。
返回值:若关文件动作成功则返回0,有错误发生时则返回EOF,并把错误代码存到errno。
描述:C 库函数 int fclose(FILE *stream) 关闭流 stream。刷新所有的缓冲区。
fclose()用来关闭fopen()打开的文件,此动作会让缓冲区内的数据写入文件中,并释放系统所提供的文件资源。
例子
思考控制台为什么没有打印出内容
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE* fp;
fp = fopen("./demo.txt", "w");
//判断文件是否打开失败
if (fp == NULL) {
perror("打开文件错误:");
exit(0);
}
char buf[12] = "helloworld!";
int i = 0;
while (buf[i] != 0) {
fputc(buf[i],fp);
i++;
};
//fflush(fp);//把缓冲区的内容刷新到磁盘中,下次open
//fclose(fp);//也可以吧缓冲区的内容刷新到磁盘中
fp = fopen("./demo.txt", "r");
char buff[1024] = "";
i = 0;
//int a = fgetc(fp);
//char b = (char)a;
//char c = fgetc(fp);
while ((buff[i] = fgetc(fp)) != -1) {
i++;
};
printf("%s", buff);
fclose(fp);
return 0;
}
4.4、fgetc
fgetc 是 file get char 的缩写,意思是从指定的文件中读取一个字符。fgetc() 的用法为:
int fgetc (FILE *fp);
fp 为文件指针。fgetc() 读取成功时返回读取到的字符,读取到文件末尾或读取失败时返回EOF。
EOF 是 end of file 的缩写,表示文件末尾,是在 stdio.h 中定义的宏,它的值是一个负数,往往是 -1。fgetc() 的返回值类型之所以为 int,就是为了容纳这个负数(char不能是负数)。
EOF 不绝对是 -1,也可以是其他负数,这要看编译器的实现。
4.5、EOF的说明
EOF 是 end of file 的缩写,表示文件末尾,是在 stdio.h 中定义的宏,它的值是一个负数,往往是 -1。fgetc() 的返回值类型之所以为 int,就是为了容纳这个负数(char不能是负数)。
EOF 本来表示文件末尾,意味着读取结束,但是很多函数在读取出错时也返回 EOF,那么当返回 EOF 时,到底是文件读取完毕了还是读取出错了?我们可以借助 stdio.h 中的两个函数来判断,分别是 feof() 和 ferror()。
4.6、fputc
字符写入函数 fputc
fputc 是 file output char 的所以,意思是向指定的文件中写入一个字符。fputc() 的用法为:
int fputc ( int ch, FILE *fp );
ch 为要写入的字符,fp 为文件指针。fputc() 写入成功时返回写入的字符,失败时返回 EOF,返回值类型为 int 也是为了容纳这个负数。例如:
fputc('a', fp);
或者:
char ch = 'a';
fputc(ch, fp);
表示把字符 'a' 写入fp所指向的文件中。