在学习c语言中,你对文件了解多少呢?
这篇博客我对文件的操作进行了总结,希望能对友友们提供帮助(比心)
目录
1.什么是文件(分类)
首先,让我来简要介绍一下什么是文件。
文件存于磁盘(硬盘)上,按照文件的功能,可以分为程序文件和数据文件
程序文件:即文件的内容是程序,包括 源程序文件(后缀为.c),目标文件(后缀为.obj),可执行程序(后缀为.exe)
数据文件:存储的就不是程序,而是程序运行时所要读取或写入的数据,根据数据的组织形式,分为二进制文件和文本文件
二进制文件:我们知道,数据在内存中以二进制存储,如果不加转化的输出到外存的文件中,生成的就是二进制文件
文本文件:将内存中的二进制数据转化为ASCII码,再存到外存的文件中,生成的就是文本文件
一个数据在文件中的存储方式:
字符型一律按ASCII码的形式存储
整型既可以按ASCII码的形式存储,也可以按二进制的形式存储
2.文件的打开和关闭
2.1流
程序从外部设备接收数据,以及将数据输出到外部设备上各需要进行一系列的复杂操作,这对于程序员来说,学习便变得困难起来,所以为了方便程序员学习,我们将这些操作抽象为流
所以可以说,c语言程序对外部设备(键盘,屏幕等)进行输入和输出时,都是对流来进行操作的
看到这里,你是否会想起,我们平常在练习c语言的时候,好像并没有涉及到流的操作呀?
其实,在c语言程序启动的时候,会默认打开3个流:
- stdin - 标准输入流,在大多数的环境中从键盘输入,scanf函数就是从中读取数据。
- stdout - 标准输出流,大多数的环境中输出至显示器界面,printf函数就是将信息输出到这个流中。
- stderr - 标准错误流,大多数环境中输出到显示器界面。
这三个流被称为标准流,它们的类型是FILE*,也就是文件指针。
2.2文件指针
每一个被使用的文件,系统都会在内存中开辟一块空间用来存放文件的相关信息,被称作文件信息区。这些信息被保存在一个结构体中,由系统命名为FILE。
VS2013 编译环境中的文件类型结构体声明如下:
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
每当打开一个文件的时候,系统会根据文件的情况自动创建⼀个FILE结构的变量,并填充其中的信 息 ,为了维护这个信息,我们通常通过创建FILE*类型的指针来操作。
过文件指针变量能够间接找到与它关联的文件。以下创建一个文件指针:
FILE* pf;
2.3文件的打开与关闭
2.3.1文件的打开
就像我们喝一瓶水,需要打开和关闭瓶盖,对文件的操作也有相应的打开和关闭。
文件的打开我们用的是函数fopen:
fopen的返回值为文件指针类型,所以我们要用文件指针来接收;filename代表文件名;mode代表的是文件打开的模式,如果打开文件失败,函数返回值为NULL。
一定要注意!文件打开后要检查fopen的返回值是否为空!
2.3.2文件的打开模式
文件打开模式 | 含义 | 如果指定文件不存在 |
---|---|---|
“r”(只读) | 1.为从文件中读取数据,打开⼀个已经存在的文本文件 2.只能从文件读取内容 3.打开文件后,不会清空文件内原有内容 | 出错 |
“w”(只写) | 1.为向文件中写数据,打开⼀个文本文件 2.只能向文件写入内容 3.打开文件后,会清空文件内原有的内容 | 建立⼀个新的文件 |
“a”(追加) | 1.向文本文件尾添加数据 2.只能向文件写入内容 3.打开文件后,不会清空文件内原有内容 | 建立⼀个新的文件 |
“rb”(只读) | 为从文件中读取数据,打开⼀个二进制文件 | 出错 |
“wb”(只写) | 为向文件中写数据,打开⼀个二进制文件 | 建立⼀个新的文件 |
“ab”(追加) | 向⼀个二进制文件尾添加数据 | 建立⼀个新的文件 |
“r+”(读写) | 1.为了读和写,打开⼀个文本文件 2.既可读取,又可写入 3.打开文件后,不会清空文件内原有内容 | 出错 |
“w+”(读写) | 1.为了读和写,建立⼀个新的文件 2.既可读取,又可写入 3.打开文件后,会清空文件内原有的内容 | 建立⼀个新的文件 |
“a+”(读写) | 1.打开⼀个文件,在⽂件尾进行读写 2.既可读取,又可写入 3.打开文件后,不会清空文件内原有内容 | 建立⼀个新的文件 |
“rb+”(读写) | 为了读和写打开⼀个二进制文件 | 出错 |
“wb+”(读写) | 为了读和写,新建⼀个新的二进制文件 | 建立⼀个新的文件 |
“ab+”(读写) | 打开⼀个二进制文件,在⽂件尾进行读和写 | 建立⼀个新的文件 |
对于文件的打开模式,我们重点记忆“r”,“w”,“a”。
2.3.3文件的关闭
文件的关闭使用函数fclose
这里也要注意!关闭文件后并不代表文件指针也消失了,所以切记将原先指向该文件的指针置空! 这可以有效避免野指针的出现。
下面写一个文件打开与关闭的大致的流程:
int main ()
{
FILE * pFile;
//打开⽂件
pFile = fopen ("myfile.txt","w");
if(pFile==NULL)
{
perror("myfile.txt");
return 1;
}
//进行文件操作
//关闭⽂件
fclose (pFile);
pFile=NULL;
return 0;
}
3.文件的顺序读写
以上函数比较简单,我们需要做到在编写程序的时候按照函数的参数进行运用即可,这里就不再举例。
4.文件的随机读写
知道了文件的顺序读写,接下来就可以看几个函数,这几个函数可以进行文件的随机读写。
4.1 fseek
通过文件指针的位置和给定偏移量来定位文件指针
通俗来说就是将光标移到你想要的位置上
SEEK_SET就是从文件头部位置算偏移量
SEEK_CUR就是从当前位置算偏移量
SEEK_END就是从尾部开始算偏移量
如下例,在s后面插入字符:
int main ()
{
FILE * pFile;
pFile = fopen ( "date.txt" , "wb" );
fputs ( "He is kind." , pFile );
fseek ( pFile , 5 , SEEK_SET );
fputs ( " very" , pFile );
fclose ( pFile );
return 0;
}
4.2 ftell
返回文件指针当前距离起始位置的偏移量
如下使用即可
long size = ftell (pFile);
printf ("Size of myfile.txt: %ld bytes.\n",size);
4.3 rewind
让文件指针回到文件的初始位置
5.关于文件读取结束
5.1文件读取结束的判断
我们根据顺序读写的函数返回值来判断文件读取是否结束
- fgetc 判断是否为 EOF(文本文件)
- fgets 判断返回值是否为 NULL(文本文件)
- fread判断返回值是否小于实际要读的个数(二进制文件)
5.2判断文件读取结束的原因
这里要介绍两个函数
5.2.1 feof
feof的作用是判断文件读取结束是否是因为遇到了文件尾
如果遇到了,那么返回一个非零的数字,如果没遇到,则返回0。
5.2.2 ferror
ferror的作用是判断文件读取结束是否是遇到了错误
如果无错误出现时返回0;有错误出现时,返回一个非零值
所以在文件操作结束后,在文件关闭之前,我们需要加这样一段代码
if (ferror(fp))
puts("I/O error when reading");
else if (feof(fp))
puts("End of file reached successfully");
6.文件缓冲区
关于文件缓冲区,这里简要的介绍一下
所谓文件缓冲区,就是系统自动为正在使用的文件在内存中开辟的一块空间。数据从内存输入到硬盘中时,会先暂存到文件缓冲区,充满文件缓冲区时,再一起输送到磁盘;从磁盘中读取数据也是一样,都要先经过文件缓冲区。
在程序运行结束后系统也会自动刷新文件缓冲区,将数据送达相应地方
就像是老师回答同学的问题一样,积攒起来一起问,要比一个一个去问效率高
所以文件缓冲区的存在有效提高了文件读写的效率
-------------------------------------------------------------------------------------------------------------------------------
以上就是关于文件的所有内容啦,看完的小伙伴记得点颗心心关注或者收藏一下哦(比心)