c语言学习第三十四课——文件二

简介: c语言学习第三十四课——文件二

二进制写文件

函数fwrite

39185f8444c143819d52363dd4b472c8.png

函数返回类型为读取到的完整的元素的个数,参数为所写的元素的地址,一个元素的大小,写的元素的个数,文件指针

这里需要注意的是,为了输入数据,打开的是一个二进制文件,这里fopen打开方式为rb(只读)或这rw(只写)。

例如

函数fread

b19a52afdc434c5881ddb96d2de30a75.png

二进制读文件

函数整体结构与fwrite相似,函数返回类型为读取到的完整的元素的个数,参数为所写的元素的地址,一个元素的大小,写的元素的个数,文件指针。

运行结果,打开文件,我们会发现里面是看不懂的符号,即里面存放的是二进制的数据,这时再用二进制读取文件内容便可以明白所存存放的数据。

我们可以发现两个函数中所读取的元素,可以是整形,浮点型,结构体型等等。

#include<stdio.h>
struct S
{
  char name[20];
  int age;
  double score;
};
int main()
{
  FILE* pf = fopen("test.dat","rw");
  if (pf == NULL)
  {
        perror("fopen");
    return 1;
  }
  struct S s = { "zhangsan",18,95.5 };
  fwrite(&s,sizeof(s),1,pf);//写文件
  fread(&s, sizeof(s), 1, pf);//读文件
  printf("%s %d %f", s.name, s.age, s.score);
  fclose(pf);
  pf = NULL;
  return 0;
}

两个返回值都是成功读到的元素的个数。

通讯录文件版本

这里我们在上次动态存储的通讯录的基础上再做调整。

主要做这几个调整:

1.在通讯录退出之前,将信息保存到文件中。

这里所保存到的文件名为“contact.dat”,

void Savecontact(Contact* pc)
{
  FILE* pf = fopen("contact.dat","r");
  if (pf == NULL)
  {
    perror("Savecontact::fopen");
    return;
  }
  //写数据
  int i = 0;
  for (i = 0; i <pc-> size; i++)
  {
    fwrite(pc->data+i, sizeof( peoInfo), 1, pf);
  }
  //关闭文件
  fclose(pf);
  pf = NULL;
  printf("保 存 成 功 !\n");
}

注意保存到文件中的是二进制,我们输出到屏幕时利用fread读取文件。

2.加载文件信息到通讯录

该函数作用在打开文件的时候:

当然在加载时需检查此时的容量,需要之前写的加载容量的函数。

void loadcontact(Contact *pc)
{
  //打开文件
  FILE *pf= fopen("contact.dat", "rb");
  if (pf == NULL)
  {
    perror("fopen");
    return;
  }
  //读文件
  peoInfo tmp = {0};
  while (fread(&tmp,sizeof(peoInfo),1,pf))
  {
    //检查容量
    checkcapacity(pc);
    pc->data[pc->size] = tmp;
    pc->size++;
  }
}

   简单的通讯录 附带文件实现 - 代码片段 - Gitee.com

这是该代码的完整实现。

此就完成了文件的保存。

fseek函数  文件的随机读写

4b09892e1a8e445897e7f48127e5892d.png

可以看出返回类型为 整形(如下图)    参数为(文件流,偏移量,起始位置)。

注意这里可以用ferror来判断。

这里说下起始位置:


3bb2e2bffb9746c28b525433d39b1332.png

函数参数里,最后一项即是起始位置,即你从哪里开始决定偏移,这个参数有三种写法,你可以写SEEK_ET 开头,SEEK_CUR  文件当前位置   SEEK_END文件末尾位置,这三种写法将决定你偏移到某位置时,偏移量的大小。

函数的应用:

int main()
{
  FILE* pf = fopen("test.dat", "r");//文件放入abcdef
  if (pf == NULL)
  {
    return 1;
  }
  //读文件
  int ch = fgetc(pf);//a
  printf("%c", ch);
   ch = fgetc(pf);//b
  printf("%c", ch);
   ch = fgetc(pf);//c
  printf("%c", ch);
  ch = fgetc(pf);//d
  printf("%c", ch);
  //这里想要读到 b
  fseek(pf, 1, SEEK_SET);//这里叫让文件从最开始往偏移1个位置
  //fseek(pf, -3, SEEK_);//这里从当前位置往后偏移3个位置指向b
   ch = fgetc(pf);
  printf("%c", ch);
   //关闭文件
    fclose(pf);
    pf=NULL;
    return 0;
}

这里偏移几个,往前偏移,就是-几个,往后偏移,就是几个。

ftell函数

5b0929f464744d66ae1315c1767fd064.png

long int ftell(FILE *stream);

返回值为整形,参数为文件流。

函数作用是返回指针相对于起始位置的偏移量。

int main()
{
  FILE* pf = fopen("test.dat", "r");//文件放入abcdef
  if (pf == NULL)
  {
    return 1;
  }
  //读文件
  int ch = fgetc(pf);//a
  printf("%c", ch);
   ch = fgetc(pf);//b
  printf("%c", ch);
   ch = fgetc(pf);//c
  printf("%c", ch);
  ch = fgetc(pf);//d
  printf("%c", ch);
    printf("%d\n",ftell(pf));//返回四,当前位置与起始位置相差四个元素,偏移量为4。
  //关闭文件
     fclose(pf);
     pf=NULL;
     return 0;
}

文本文件与二进制文件

数据文件被称为文本文件或者二进制文件。

数据在内存中以二进制的形式存储,去过不加转换的输出外村,就是二进制为文件。

如果要求在外村上以ASCLL码的形式存储,则需要再存储前转换,以ASCLL字符的形式存储的文件就是文本文件。

一个数据在内存中是如何存放的呢?

字符一律以ASCII形式存储,数值型数据既可以以ASCII码形式存储,也可以使用二进制存储。

文件读取结束的判定

被错误使用的feof,

f3967f6516bd44b68c85cb991a4100b6.png

文件读取结束的判定 feof

牢记:在文件读取过程中,不能使用feof函数的返回值直接判断是否结束

feof的作用是:当文件读取已经结束时候,判断读取结束的原因是否是遇到文件结束。这里的判断文件结束根据不同的函数,判断方式不同。

例如在fgtec中 判断返回是否为eof

       在fgets函数中判断返回是否为NULL;

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

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

文件缓冲区

文件缓冲区即系统在读写程序时在内存中开辟的数据源与数据目标中间的一个用于保存完整数据内容的缓冲区域。 目前C语言使用的文件系统分为缓冲文件系统(标准I / O)和非缓冲文件系统(系统I / O)。 缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用,当执 行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读入接收的变量。

这里可以类比输入输出缓冲区。

最后实现一个代码  拷贝一个文件

int main()
{
  //实现一个代码
  //打开两个文件  被读的,被写的
  FILE* pfread = fopen("text.txt", "r");
  if (pfread == NULL)
  {
    fclose(pfread);
    pfread = NULL;
    return 1;
  }
  FILE* pfwrite = fopen("text.txt", "r");
  int ch = 0;
  while ((ch = fgetc(pfread)) != EOF)
  {
    ch=fgetc(ch, pfread);
    fputc(ch, pfwrite);
  }
  fclose(pfwrite);
  pfwrite = NULL;
  return 0;
}

一起加油!!

相关文章
|
2月前
|
存储 编译器 C语言
如何在 C 语言中判断文件缓冲区是否需要刷新?
在C语言中,可以通过检查文件流的内部状态或使用`fflush`函数尝试刷新缓冲区来判断文件缓冲区是否需要刷新。通常,当缓冲区满、遇到换行符或显式调用`fflush`时,缓冲区会自动刷新。
|
2月前
|
存储 编译器 C语言
C语言:文件缓冲区刷新方式有几种
C语言中文件缓冲区的刷新方式主要包括三种:自动刷新(如遇到换行符或缓冲区满)、显式调用 fflush() 函数强制刷新、以及关闭文件时自动刷新。这些方法确保数据及时写入文件。
|
2月前
|
C语言
【C语言】探索文件读写函数的全貌(三)
【C语言】探索文件读写函数的全貌
|
2月前
|
存储 C语言
【C语言】探索文件读写函数的全貌(二)
【C语言】探索文件读写函数的全貌
|
2月前
|
C语言
教你快速理解学习C语言的循环与分支
教你快速理解学习C语言的循环与分支
17 0
|
2月前
|
C语言
【C语言】探索文件读写函数的全貌(一)
【C语言】探索文件读写函数的全貌
|
2月前
|
存储 文件存储 C语言
【C语言】深入了解文件:简明指南
【C语言】深入了解文件:简明指南
|
3月前
|
Linux C语言
C语言 文件IO (系统调用)
本文介绍了Linux系统调用中的文件I/O操作,包括文件描述符、`open`、`read`、`write`、`lseek`、`close`、`dup`、`dup2`等函数,以及如何获取文件属性信息(`stat`)、用户信息(`getpwuid`)和组信息(`getgrgid`)。此外还介绍了目录操作函数如`opendir`、`readdir`、`rewinddir`和`closedir`,并提供了相关示例代码。系统调用直接与内核交互,没有缓冲机制,效率相对较低,但实时性更高。
|
4月前
|
存储 C语言
【C语言】C语言-学生成绩管理系统(源码+数据文件+课程论文)【独一无二】
【C语言】C语言-学生成绩管理系统(源码+数据文件+课程论文)【独一无二】
58 15
|
4月前
|
存储 C语言
【c语言】职工信息管理系统 包含读取写入txt文件,职工信息的增删改查
【c语言】职工信息管理系统 包含读取写入txt文件,职工信息的增删改查