🙉本文将继续对文件操作相关知识进行讲解
1. 文件的随机读写
1.1 fseek
fseek函数原型:
fseek简而言之就是设置文件中的光标,stream就指向对象文件的指针,offset是文件中光标处相对于起始位置的偏移量,origin是光标所在位置
origin:
SEEK_CUR | 文件指针(光标)当前位置 |
SEEK_SET | 文件起始位置 |
SEEK_END | 文件的末尾位置 |
1.2 ftell
ftell函数原型:
ftell的功能就是返回贯标相对于起始位置的偏移量
1.3 rewind
rewind函数原型:
rewind的功能用于将光标的位置设置为文件的起始位置处
来看下面的代码:事先向data.txt中写入abcdef
int main()
{
FILE* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
int ch = fgetc(pf);
printf("%c\n", ch); //a
ch = fgetc(pf);
printf("%c\n", ch); //b
ch = fgetc(pf);
printf("%c\n", ch); //c
ch = fgetc(pf);
printf("%c\n", ch); //d
int i = ftell(pf); //返回偏移量
printf("%d\n", i);
fseek(pf, -4, SEEK_CUR); //设置光标
rewind(pf); //光标回到初始位置
ch = fgetc(pf);
printf("%c\n", ch);
fclose(pf);
pf = NULL;
return 0;
}
打印结果:
a b c d 4 a
2. 文本文件和二进制文件
数据文件分为文本文件和二进制文件,内存中数据是以二进制形式存储的,将内存中的数据不经转换直接存储到外存,称为二进制文件;如果要外存中的数据以ASCII形式存储,则应将内存中的数据进行转换,以ASCII形式存储字符的文件称为文本文件
将10000写到二进制文件中
int main()
{
int a = 10000;
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fwrite(&a, 4, 1, pf);
fclose(pf);
pf = NULL;
return 0;
}
用vs2022以二进制编译器的形式打开data.txt:
先不用管前面的8个0,来看一下10 27 00 00是怎么来的
10000的二进制形式:0000 0000 0000 0000 0010 0111 0001 0000
转换为16进制:00 00 27 10
由于vs是小端存储模式,所以在内存中存储的是:10 27 00 00
将10000以二进制的形式存储到文件中用4个字节
以ASCII的形式存储到文件中占用5个字节(以字符形式存储)
3. 文件读取结束的判定
feof函数原型:
feof用于判断文件读取结束后,是在读取过程中因为遇到错误而结束还是正常读取结束,
在读取文本文件文件过程中fgetc读取错误则返回EOF,fgets读取错误则返回NULL;
在读取二进制文件过程中fread返回其读取到的元素个数这是fread的函数原型:size_t fread(void* ptr, size_t size, size_t count, FILE * stream);假如fread每次读取5个元素,但如果文件中只有11个元素,前两次返回的结果为5,最后一次文件中只剩一个元素,那么fread只会读取这一个元素,返回结果也就是1,
int main()
{
FILE* pfread = fopen("data1.txt", "r");
if (pfread == NULL)
{
perror("fopen");
return 1;
}
int ch = 0;
while ((ch = fgetc(pfread)) != EOF)
{
;
}
if (ferror(pfread))
{
printf("遇错结束,读取失败");
}
else if (feof(pfread))
{
printf("正常结束,读取成功");
}
return 0;
}
4. 文件缓冲区
系统会自动给正在使用的文件在内存中开辟一块文件缓冲区,当程序中的数据输出到文件中时,会将这些数据先放在输出缓冲区,当输出缓冲区满时再传输到磁盘中,当要将文件中的数据输入到程序数据区时,会将这些数据先放在输入缓冲区,当输入缓冲区满时再传输到程序数据区中
接下来给出一段代码来证明文件缓冲区是存在的:
int main()
{
FILE* pf = fopen("data.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
fputs("abcdef", pf);//先将数据写到了缓冲区,由于还没有刷新缓冲区,数据此时仍然在缓冲区
printf("睡10秒\n");
Sleep(10000);//再程序睡眠期间打开文件,发现此时文件为空
fflush(pf); //刷新缓冲区:将缓冲区中的数据写到文件中
printf("睡5秒\n");
Sleep(5000);//此时程序睡眠期间,数据已经写到了文件中
fclose(pf);//关闭文件的操作也会刷新缓冲区
pf = NULL;
return 0;
}