文件的随机读写
在syseptember的个人博客:文件操作我们介绍了文件的顺序读写以及相相关函数,由于顺序读写的函数每次操作文件之后文件中的位置指示器只能像后面移动,这就导致了我们没有对位置指示器
前面的字符进行访问,所以C语言对文件的操作还支持随机读写,随机读写可以改变文件中的位置指示器
的值
在计算机系统中,
位置指示器
(英文:position indicator)是一种用于记录或指示某个数据结构或文件中当前位置或偏移量的指针或标记。
例如,在文件系统中,位置指示器可以指示文件中当前的读取或写入位置。当文件被打开时,位置指示器通常被设置为文件的起始位置,然后在读取或写入数据时会随着操作的进行而移动。对于随机访问文件,位置指示器通常可以随意移动到任何位置。而对于顺序访问文件,则只能按照顺序从前往后移动。
文件中的位置指示器通常由操作系统内核维护,因此存储在内存中。每个打开的文件都有一个与之相关联的位置指示器,该指示器存储了当前读取或写入位置的信息。
fseek
- 将与流关联的位置指示器设置到新位置
- 对于以二进制模式打开的流,新位置是通过将偏移量添加到由 origin 指定的参考位置来定义的。
- 对于以文本模式打开的流,offset 应为零或由先前调用 ftell 返回的值,并且 origin 必须为 SEEK_SET。
- 如果使用这些参数的其他值调用函数,则支持取决于特定系统和库实现(不可移植)
- stream参数是需要修改位置指示器的文件指针,offset是距离参数orign的偏移量,orign参数是由头文件stdio.h所定义的常量,SEEK_SET是文件的开始位置,SEEK_CUR是文件的当前位置指示器的位置,SEEK_END是文件的结束位置
ftell
- 返回流的位置指示符的当前值。
- 对于二进制流,这是从文件开头算起的字节数。
- 对于文本流,该数值可能没有意义,但仍可用于稍后使用 fseek 将位置恢复到相同位置(如果使用 ungetc 放回的字符仍在等待读取,则行为未定义)。
- 函数执行失败时,返回 -1,并将 errno 设置为系统特定的正值。
rewind
- 将与流关联的位置指示器设置为文件的开头
- 成功调用此函数后,与流关联的文件结束和错误内部指示符将被清除,并且先前调用 ungetc 对此流的所有影响都将被删除。
文本文件和二进制文件
根据数据的组织形式,数据文件被称为文本文件或者二进制文件。
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。
一个数据在内存中是怎么存储的呢?
字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。
如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而
二进制形式输出,则在磁盘上只占4个字节(VS2013测试)。
10000以文本形式存储ASICII
00110001 00110000 00110000 00110000 00110000
10000以二进制形式存储
00000000 000000000 00100111 00010000
注意:二进制文件是指以二进制形式存储数据的文件,其中包含的数据不仅仅是字符,还可以包括整数、浮点数、结构体等各种数据类型,而且数据通常没有特定的格式要求。二进制文件不能使用文本编辑器进行编辑和查看,需要使用专门的二进制编辑器或编程语言进行读写
使用fread()
函数读取文本文件
中的整数
,可能会出现问题。因为在文本文件中,整数通常是以字符的形式进行存储的,使用fread()函数读取数据时,会将字符对应的ASCII码值读取出来,而不是实际的整数值。
使用fread()
函数读取文本文件
中的字符
通常不会出错,因为每个字符都对应着一个ASCII码值,而且每个字符都只占一个字节的空间,所以使用fread()函数读取单个字符时,可以将其读取为对应的ASCII码值
文本读取结束的判定
被错误使用的feof
牢记:在读取文件的过程中,不能使用feof()的返回值来判断文件是否读取结束
应该是用于当文件结束读取后,判断文件是否是读取完结束还是读取时遇见错误结束
文件读取结束标志
判断文件是否读取结束
文本文件
读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:
fgetc
判断是否为 EOF .
fgets
判断返回值是否为 NULL .
二进制文件
的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
fread判断返回值是否小于实际要读的个数。
文件读取结束原因
1. 当文件指示器到达文件末尾时(即文件读取完毕),文件会设置一个end of file indicator
,可以通过feof
来检测
2. 当文件读取时遇见错误而终止读取,文件会设置一个error indicator
,可以通过ferror
来检测
example for ferror
example for feof
文件缓冲区
ANSIC 标准采用“
缓冲文件系统
”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区
”。从内存向磁盘输出数据会先送到内存中的缓冲区
,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区
(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。
关于文件缓冲区想要了解跟多点文件缓冲区
验证文件缓冲区
//验证文件缓冲区
#include <Windows.h>
int main()
{
FILE* pf = fopen("test.txt", "w");
fputs("abcdef", pf);//先将数据放在输出缓冲区
printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");
Sleep(10000);
printf("刷新缓冲区\n");
fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)
//注:fflush 在高版本的VS上不能使用了
printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");
Sleep(10000);
fclose(pf);
//注:fclose在关闭文件的时候,也会刷新缓冲区
pf = NULL;
return 0;
}