在介绍文件操作函数之前,我们要先了解一下流
流
所谓流,字面理解就是水的流动,那么抽象开来就是信息流。我们在对一个对象进行输入或者输出数据的时候可能面对不同的对象需要不同的操作。对于程序员来说掌握如此多的操作就很麻烦,因此为了解决这个问题,就发明了流。我们只要向流里面输入数据或者从流里面取数据就可以。
流的分类
根据对象的不同可以分为不同的流:例如二进制文件流,标准输入输出流,字符串流,等等。只要有输入输出的地方,流都会出现。
在C语言中的流
C语言的流主要在头文件<stdio.h>中使用的到。我们使用的文件操作函数也是在这个头文件里面。标准输入输出流是,stdin和stdout,还有一个stderr。其中的stdin就是键盘输入并将信息储存在输入流中。而stdout就是输出到显示界面。
在c++里面的流
据我目前了解就是<iostram>这个流
文件操作
文件操作就是对文件进行数据的输入或者读取。
文件类型
文件有不同的类型:二进制文件,ascll码文件。其中二进制文件是存储的二进制,ascll码文件是存储的ascll码来间接存储字符,ascll码文件也叫做文本文件,我们打开是可以直接看的懂的。
这是二进制存储,是乱码
这是ascll存储,可以看到内容
文件指针
我们在写入文件信息的时候如果频繁的输入信息会很占用电脑的内存,一般是有一个文件信息区来储存很多的信息然后再一次性全部输入到文件里面。因此每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名 FILE.
所以FILE指针实际就是结构体指针。
这个结构体称为文件信息区
文件操作函数
我们首先要一个函数能够获取到我们的操作流,以及获取怎样的流:输入流,输出流还是输入输出流,或者是二进制流.......
文件打开关闭函数
fopen
(FILE*)F=fopen("文件名","打开方式");
文件打开方式
文件名
文本文件,二进制文件的后缀都是.txt
同时,我们打开也需要关闭,否则我们的信息就不会写入到文件里面,只是存储到文件缓冲区里面。
fclose
int fclose ( FILE * stream );
返回值有两个,一个是返回0表示关闭文件成功,一个是返回EOF表示文件关闭失败。
所以我们可以在最后判断一下我们是否正常关闭了文件。
当文件关闭成功,文件缓冲区的信息就会写入文件中。
文件缓冲区存在证明
我们通过调试来一步一步查看
首先是执行创建a.txt创建的操作
然后是fprintf
我们发现没有写进去
然后是fputs
依然是没有
最后我们关闭文件,让文件缓冲区的信息写入到文件中
所以文件缓冲区是存在的,有些函数的使用就能够刷新文件缓冲区。这里的fclose就是一个例子。
也得出结论,我们进行文件操作的时候一定要在最后写fclose,否则可能导致文件缓冲区的信息没有写入到文件中。虽然最后vs会默认帮你将缓冲区的信息写入,但是这不能保证每次都能成功。
fflush
int fflush(FILE *stream)这个函数是刷新缓冲区的,将缓冲区的内容提前写入文件,成功则该函数返回一个非零值,否则返回零。
文件指针的位置
这个就等价于平时打字的光标,我们默认写入时,光标是在最开始的地方的。随着写入函数使用,光标就会后移。下一次的写入函数会在这个光标基础上向后写
输入输出函数
函数的返回值和输入参数。
int fgetc (FILE *stream)
int fputc (int char, FILE *stream)
char* fgets (char *str, int n, FILE *stream)
int fputs (const char *str, FILE *stream)
int fprintf (FILE *stream, const char *format, ...)
int fscanf (FILE *stream, const char *format, ...)
size_t fread (void *ptr, size_t size, size_t nmemb, FILE *stream)
size_t fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream)
fgetc
读取当前文件指针的字符,返回字符对应的ascll码,如果接收失败或者读取至文件的末尾则返回EOF(-1)
fputc
从当前的文件指针处放入一个字符,如果成功放入则返回正值,否则返回0;
fgets
从当前的文件指针开始向后读取n个字符,如果读取完毕则返回和str一样的地址,如果读取失败或者读取到末尾就返回NULL
fputs
从当前文件指针处存放str中的数据,如果成功放入则返回正值,否则返回EOF
fprintf
从当前文件指针处存放格式化数据,成功则返回写入字符的字数。失败则返回EOF
fscanf
从当前文件指针处取出格式化数据。字符串的取出和标准输入一样,空格和回车键为一个字符串终止。成功返回成功接受的字符个数,失败返回EOF
fread
从当前文件指针处读取数据,要输入数据的读取格式,读取的长度。返回成功读取的长度,读取失败返回EOF
fwrite
从当前文件指针处写入数据,要输入数据的读取格式,读取的长度。返回成功输入的长度,读取失败返回EOF
注意点
我们这里的从当前文件指针处写入或者读取是指当我们的文件缓冲区刷新后才生效的。这里的函数不是直接写入到文件中的。
补充
我们写FILE *stream时,可以写stdio/stdout。这样写就和printf、scanf、putc、getc、puts和gets相同了。但是fgets优于gets,因为它接受字符串有长度限制,可以防止字符串长度不够导致访问越界报错的问题
文件指针操作
long int ftell(FILE *stream)
void rewind(FILE *stream)
int fseek(FILE *stream, long int offset, int whence)
ftell
告诉当前文件指针的相对于起始位置的偏移量
rewind
将文件指针的位置重置到文件开头位置
fseek
改变文件指针的位置
这里的whence有三个
SEEK_SET | 文件的开头 |
SEEK_CUR | 文件指针的当前位置 |
SEEK_END | 文件的末尾 |
set current 和end
offset表示基于这个位置将指针左右移动的长度,用正负表示方向。
-表示向文件初始位置移动,+表示向文件末尾移动
通过以上函数来检测文件的字符数
文件读取结束的判定
feof
int feof(FILE *stream)
文件结束时,该函数返回一个非零值,否则返回零。
feof 的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件尾结束。如果遇到文件读取错误,而导致文件结束feof是无法判断的。所以我们不能直接用feof的返回值来作为文件的结束标志
ferror
int ferror(FILE *stream)
如果文件读取错误,该函数返回一个非零值,否则返回一个零值。
这是判断是否以错误输入输出而导致的文件读取结束。也不能只直接作为文件结束的标志
正确的文件结束标志
1. 文本文件读取是否结束,判断返回值是否为EOF ( fgetc ),或者NULL ( fgets )
例如:
• fgetc 判断是否为EOF .
• fgets 判断返回值是否为NULL .
2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
3.同时使用feof和ferror。两种情况都兼顾就能判断是否文件结束了。
举例