【文件随机读写和文件缓冲区】

简介: 1.1fseek函数根据文件指针的位置和偏移量来定位文件指针。看不懂没关系,举个例子你就明白了。我们首先在text.txt文件中放入 “abcdef” 这些字符。

1.1fseek函数

根据文件指针的位置和偏移量来定位文件指针。

int fseek ( FILE * stream, long int offset, int origin );

看不懂没关系,举个例子你就明白了。

我们首先在text.txt文件中放入 “abcdef” 这些字符。


7ed339d572344eea8bcd59c532d511aa.png

int main()
{
  FILE* pf = fopen("text.txt", "r");
  int ch = 0;
  if (pf == NULL)
  {
    perror("fopen");
  }
  else
  {
    ch = fgetc(pf);
    printf("%c\n", ch);//a
    ch = fgetc(pf);
    printf("%c\n", ch);//b
    ch = fgetc(pf);
    printf("%c\n", ch);//c
  }
  return 0;
}

然后我们用fgetc函数读取三个字符,注意,fgetc函数,每读取完一个字符,光标就会自动跳转到下一位,此时已经读取完三个字符了,光标自然就指向了d位置,再读取的时候,就会读取d。

但是我不想读取d位置了,我想回头读取b位置。

此时有对fseek函数来说,有三种方法:


15e67f0d493b47719acb9fc59d9bc876.png

如果这样输入:

fseek(pf, 1, SEEK_SET);

5e188a2958e44ff28fddc53a129ffaae.png

结果证实了上述结论。

我们还可以这样写:

fseek(pf, -2, SEEK_CUR);

对标上面的图,是从当前位置的光标,向左移动2个光标位置,当前位置的光标是在d处,向左移动2个位置,就移动到了b处,此时读取,就读取到了b。

3b99f721a473442d9cdfdc0642f7010c.png

至于最后一种方式,SEEK_END 这样的读取方式,较难以使用,因为本来就不知道文件有多长,有多少数据,不过这种方式可以使用ftell函数来代替。

1.2 ftell函数

ong int ftell ( FILE * stream );

返回文件指针相对于起始位置的偏移量

ftell函数返回的是从当前位置相对于起始位置的偏移量。

仍以上面的例子为例

int main()
{
  FILE* pf = fopen("text.txt", "r");
  int ch = 0;
  if (pf == NULL)
  {
    perror("fopen");
  }
  else
  {
    ch = fgetc(pf);
    printf("%c\n", ch);//a
    ch = fgetc(pf);
    printf("%c\n", ch);//b
    ch = fgetc(pf);
    printf("%c\n", ch);//c
    int a = ftell(pf);
    printf("%d\n", a);
  }
  return 0;
}

此时光标移动到了c位置,使用ftell函数,返回相对起始位置的偏移量,即 3

1.3 rewind函数

void rewind ( FILE * stream );

ewind 让文件指针的位置回到文件的起始位置

相比之下,ftell函数和rewind函数更加简单粗暴。

int main()
{
  FILE* pf = fopen("text.txt", "r");
  int ch = 0;
  if (pf == NULL)
  {
    perror("fopen");
  }
  else
  {
    ch = fgetc(pf);
    printf("%c\n", ch);//a
    ch = fgetc(pf);
    printf("%c\n", ch);//b
    ch = fgetc(pf);
    printf("%c\n", ch);//c
    rewind(pf);
    ch = fgetc(pf);
    printf("%c\n", ch);//a
  }
  return 0;
}

举一个例子,就可以理解了。

2. 被误解的feof函数

在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。
而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。

文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL( fgets )

例如:

fgetc 判断是否为 EOF .

fgets 判断返回值是否为 NULL .


二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。

例如:

fread判断返回值是否小于实际要读的个数。

举个简单例子:

int main(void)
{
  int c; // 注意:int,非char,要求处理EOF
  FILE* fp = fopen("test.txt", "r");
  if (!fp) {
    perror("File opening failed");
    return EXIT_FAILURE;
  }
  //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
  while ((c = fgetc(fp)) != EOF) 
  {
    putchar(c);
  }
  //判断是什么原因结束的
  if (ferror(fp))
    puts("I/O error when reading");
  else if (feof(fp))
    puts("End of file reached successfully");
  fclose(fp);
}


当读取结束时,无论是读取失败还是遇到文件末尾, 都会返回EOF,此时就有两种情况,分别用ferror和feof函数进行判断即可。

2.1 文件缓冲区

ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序

中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装

满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓

冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根

据C编译系统决定的。


2ae61a9c0b2c44db9c6a98369c068ee6.png

意思是这样的:

当我们写程序向文件中写入信息时,这些信息会先被放在输出缓冲区中,当输出缓冲区被充满后,再依次送到硬盘中。
当我们写程序向文件中读取信息时,这些信息会先被放在输入缓冲区中,当输入缓冲区被充满后,再依次送到我们手中。


3112607ae46b4c498a96899f3656a6b8.gif

相关文章
|
前端开发 JavaScript 网络协议
深入理解Python Web开发中的前后端分离与WebSocket实时通信技术
【7月更文挑战第18天】前后端分离采用Flask/Django框架,前端JavaScript框架如Vue.js与后端通过AJAX/Fetch通信。WebSocket提供实时双向通信,Python可借助websockets库或Flask-SocketIO实现。最佳实践包括定义清晰的接口规范,确保安全性(HTTPS,认证授权),优化性能,和健壮的错误处理。结合两者,打造高效实时应用。
228 1
|
算法 C语言
如何用C语言轻松判断回文数?
如何用C语言轻松判断回文数?
|
11月前
|
开发者
深入了解HTTP状态码
深入了解HTTP状态码
386 64
|
10月前
|
JavaScript 前端开发
Moment.js与其他处理时间戳格式差异的JavaScript库相比有什么优势?
Moment.js与其他处理时间戳格式差异的JavaScript库相比有什么优势?
|
10月前
|
Java 应用服务中间件 测试技术
NoInitialContextException 异常通常会在哪些场景下出现
NoInitialContextException 异常通常在尝试使用 JNDI(Java 命名和目录接口)进行资源查找时,因缺少必要的环境配置或初始化上下文未正确设置而出现。常见于 Java EE 应用中。
156 5
|
SQL 缓存 Java
Mybatis框架
Mybatis框架
|
弹性计算 Ubuntu 网络协议
现在你还不知道怎么使用宝塔面板嘛,下面带你从某里云购域名开始
现在你还不知道怎么使用宝塔面板嘛,下面带你从某里云购域名开始
|
监控 数据挖掘 数据安全/隐私保护
ERP系统中的员工薪酬与福利管理
【7月更文挑战第25天】 ERP系统中的员工薪酬与福利管理
429 2
|
前端开发 BI
基于jeecgboot的大屏设计器开发——大屏报表管理(二)
基于jeecgboot的大屏设计器开发——大屏报表管理(二)
280 0
|
机器学习/深度学习 运维 算法
自编码器(Autoencoder)在无监督学习和降维中的应用
自编码器(Autoencoder)在无监督学习和降维中的应用
555 0
自编码器(Autoencoder)在无监督学习和降维中的应用