【C语言进阶】文件的顺序读写、随机读写、文本文件和二进制文件、文件读取结束的判定以及文件缓冲区相关知识(中)

简介: 【C语言进阶】文件的顺序读写、随机读写、文本文件和二进制文件、文件读取结束的判定以及文件缓冲区相关知识(中)

完成后我们再用“ 读 ”模式打开该文件,并在判断非空后使用 fgetc 函数来顺序读取该文件中的内容:

int main()
{
  FILE* p = fopen("test.txt", "r");
  //文件打开模式为“读”
  if (p == NULL)
  {
    perror("FILE_OPEN");
    return 1;
  }
  int ch = 0;
  while ((ch = fgetc(p)) != EOF)
  {
    printf("%c ", ch);
    //顺序读取文件指针pp指向文件内的信息并打印
  }
  fclose(p);
  p = NULL;
  return 0;
}

将程序编译运行起来查看我们 fgetc 函数的读取结果eb36a65b84de4f579c231cb08e5ce14f.png并且我们也可以使用 fputs 函数(区别于 fputc 函数)来实现字符串的顺序写入:

int main()
{
  FILE* p = fopen("test.txt", "w");
  //文件打开模式为“写”
  if (p == NULL)
  {
    perror("FILE_OPEN");
    return 1;
  }
  fputs("The test TXT\n", p);
  //fputc 为写入字符,fouts 为写入字符串
  //只写入字符串内容,不会自动换行,想要换行需手动添加换行转义字符\n
  //并且在写入时,会覆盖原本的内容数据
  fputs("The test TXT", p);
  fclose(p);
  p = NULL;
  return 0;
}

或使用 fgets 函数(区别于 fgetc 函数)来实现字符串的顺序读取:

int main()
{
  FILE* p = fopen("test.txt", "r");
  //文件打开模式为“读”
  if (p == NULL)
  {
    perror("FILE_OPEN");
    return 1;
  }
  char arr[256] = { 0 };
  //定义字符数组用于存放读取到的字符串
  fgets(arr, 256, p);
  //从文件指针p指向文件处,读取最多256个字符,并将数据读取至字符数组arr中
  //该函数为按行读取,读取至换行转义符\n处主动停止并换行
  printf("%s", arr);
  //想要读取两行就需要使用两次fgets函数
  fgets(arr, 256, p);
  printf("%s", arr);
  fclose(p);
  p = NULL;
  return 0;
}

最终目的,就是要结合文件操作将数据保存至本地硬盘中,从而实现优化,于是我们可以使用 fprintf 函数实现将结构体变量的内容保存至本地硬盘之中:

typedef struct Contact
{
  char name[20];
  char sex[5];
  int age;
  char tele[11];
}con;
int main()
{
  FILE* p = fopen("test.txt", "w");
  //文件打开模式为“写”
  if (p == NULL)
  {
    perror("FILE_OPEN");
    return 1;
  }
  con c1 = { "Sherry","女",18,"3478290" };
  fprintf(p, "%s %s %d %s\n", c1.name, c1.sex, c1.age, c1.tele);
    //按照"%s %s %d %s\n"的格式将数据c1.name, c1.sex, c1.age, c1.tele写入至p所指向的文件内
  fclose(p);
  p = NULL;
  return 0;
}

程序编译运行结束后关闭,这时我们再去本地文件中查看会发现,数据已经成功的保存至本地硬盘中了:

cb9b5b9e6b404350af0341f69cc2fc82.png

并且我们也可以通过 fscanf 函数从本地硬盘文件中读取数据:

typedef struct Contact
{
  char name[20];
  char sex[5];
  int age;
  char tele[11];
}con;
int main()
{
  FILE* p = fopen("test.txt", "r");
  //文件打开模式为“读”
  if (p == NULL)
  {
    perror("FILE_OPEN");
    return 1;
  }
  con c1 = { 0 };
  fscanf(p, "%s %s %d %s", c1.name, c1.sex, &(c1.age), c1.tele);
  //按照"%s %s %d %s"的格式,从p所指向的文件中将数据读取至c1.name, c1.sex, &(c1.age), c1.tele中
  printf("%s %s %d %s\n", c1.name, c1.sex, c1.age, c1.tele);
  fclose(p);
  p = NULL;
  return 0;
}

c666fe053df340c09a99307a93e1153a.png

3. 文件随机读写:

我们很多时候并不是要进行顺序读写,而是进行随机读写(伪随机,指不按照顺序依次进行读写)。为了实现这样的操作,我们就需要使用 fseekftellrewind 三个函数来帮助我们对这样的操作进行实现。

3.1 fseek 函数:

fseek 函数的作用为,根据文件指针的位置和偏移量来定位文件指针。

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

1.“ offset”为相对于指针位置的指针偏移量

2.“ origin ”为指针位置,其参数有三种:“ SEEK_CUR ”表示文件指针当前位置;“ SEEK_END ”表示文件末尾的位置;“ SEEK_SET ”表示文件开始位置

int main()
{
  FILE* p = fopen("test.txt", "r+");
  //文件打开模式为“读写”
  if (p == NULL)
  {
    perror("FILE_OPEN");
    return 1;
  }
  char ch = 'a';
  for (ch = 'a'; ch <= 'z'; ch++)
  {
    fputc(ch, p);
    //使用 fputc 函数顺序写入小写字符a~z
  }
  fseek(p, 10, SEEK_SET);
  //使用fseek函数将文件指针从文件开始处(参数SEEK_SET表示文件起始位置)指向偏移量为10处
  //偏移量为正表示向后偏移,为负表示向前偏移
  char output;
  output = fgetc(p);
  //接下来进行读取时,继续向后读取一个字符,即字符k
  printf("%c\n", output);
  fclose(p);
  p = NULL;
  return 0;
}

f977e194454249c7ad2208e455361fb2.png

3.2 ftell 函数:

long int ftell(FILE* strname);
• 1

ftell 函数的作用为,返回文件指针相对于文件起始位置的偏移量。

int main()
{
  FILE* p = fopen("test.txt", "r+");
  //文件打开模式为“读写”
  if (p == NULL)
  {
    perror("FILE_OPEN");
    return 1;
  }
  char ch = 'a';
  for (ch = 'a'; ch <= 'z'; ch++)
  {
    fputc(ch, p);
    //使用 fputc 函数顺序写入小写字符a~z
  }
  fseek(p, -5, SEEK_END);
  //使用fseek函数将文件指针从文件结尾处(参数SEEK_SET表示文件起始位置)指向偏移量为-5处
  //偏移量为正表示向后偏移,为负表示向前偏移
  long back = ftell(p);
  //定义整型变量用于接受并记录指针相对于起始位置的偏移量
  printf("指针相对于起始位置的偏移量为:%ld\n", back);
  fclose(p);
  p = NULL;
  return 0;
}

ea4d50a4b88046389c62f6dc4a6079e8.png

3.3 rewind 函数:

void rewind(FILE* strname);

rewind 函数的作用为,使文件指针位置返回文件的起始位置

int main()
{
  FILE* p = fopen("test.txt", "r+");
  //文件打开模式为“读写”
  if (p == NULL)
  {
    perror("FILE_OPEN");
    return 1;
  }
  char ch = 'a';
  for (ch = 'a'; ch <= 'z'; ch++)
  {
    fputc(ch, p);
    //使用 fputc 函数顺序写入小写字符a~z
  }
  fseek(p, -5, SEEK_END);
  rewind(p);
  //使文件指针回归文件起始位置
  printf("%c\n", fgetc(p));
  //打印验证指针当前位置
  fclose(p);
  p = NULL;
  return 0;
}

76b78845340e49e48df9a8bd047af72b.png

4. 文本文件与二进制文件:

根据数据的组织形式,我们将数据文件称为文本文件二进制文件

二进制文件:在我们的计算机内存中,各种数据都是以二进制码的形式进行存储的,以 二进制码形式进行存储的文件

文本文件:以 ASCII 字符形式进行存储的文件

如果我们想要在外存上以 ASCII 码的形式存储数据,就需要在存储前将数据进行转换。

数据在内存中数据到底是如何让进行存储的呢?

实际上,字符在内存中的存储一律是以 ASCII 码的形式进行存储的,而数值型数据既可以用ASCII 码存储,也可以用二进制形式进行存储。

例如十进制数字 10000 在进行存储时,就可以有两种存储形式:

1.二进制形式:

00000000 00000000 00100111 00010000

2.ASCII码形式:

00110001 00110000 00110000 00110000 000110000

1 0 0 0 0


int main()
{
  int a = 10000;
  FILE* p = fopen("test.txt", "wb");
  //“wb”表示以只写模式打开二进制文件
  if (p == NULL)
  {
    perror("FileOpen");
    return 0;
  }
  fwrite(&a, 4, 1, p);
  //将变量a中的数据,每四个字节存储一次,写入文件指针p所指向的文件
  fclose(p);
  p = NULL;
  return 0;
}

在上面这段代码运行成功后,我们已经成功的将变量 a 中的数据写入到了本地磁盘对应的 txt 文件中了,可是我们发现,当我们尝试打开本地文件查看存储的数据时,里面看起来并不是我们想要的结果:

005629e48a8f486d8ce1182a2936b8b4.png

相关文章
|
16天前
|
Linux C语言
C语言获取文件长度
C语言获取文件长度
|
30天前
|
安全 算法 程序员
【C/C++ 文件操作】深入理解C语言中的文件锁定机制
【C/C++ 文件操作】深入理解C语言中的文件锁定机制
33 0
|
1月前
|
存储 编译器 Linux
c语言进阶(2)
c语言进阶(2)
26 0
|
1月前
|
C语言
【进阶C语言】数组笔试题解析
【进阶C语言】数组笔试题解析
17 0
|
1月前
|
存储 程序员 C语言
【进阶C语言】C语言文件操作
【进阶C语言】C语言文件操作
42 0
|
1天前
|
存储 算法 C语言
C语言进阶:顺序表(数据结构基础) (以通讯录项目为代码练习)
C语言进阶:顺序表(数据结构基础) (以通讯录项目为代码练习)
|
19天前
|
存储 测试技术 C语言
【C语言进阶】 假期测评③
【C语言进阶】 假期测评③
41 1
|
1月前
|
存储 程序员 数据处理
C语言进阶
C语言进阶
|
1月前
|
存储 缓存 安全
c语言进阶(1)
c语言进阶(1)
19 0
|
1月前
|
存储 C语言 C++
【指针的进阶】C语言
【指针的进阶】C语言