C语言-文件操作(13.1)

简介: C语言-文件操作(13.1)

思维导图:



1. 为什么使用文件

在学习通讯录的时候,我们往通讯录里添加信息,


但是,当我们关闭程序的时候,存放在通讯录的内容就销毁了。


而使用文件我们可以将数据直接存放在电脑的硬盘上,做到了数据的持久化。


如果把通讯录数据放文件了,下一次打开也能继承上一次的数据。


2. 什么是文件

磁盘上的文件就是文件。


但是在程序设计中,我们一般谈的文件有两种:程序文件和数据文件。


2.1 程序文件

程序文件包括:


1.源程序文件(后缀为.c)


2.目标文件(windows环境后缀为.obj)


3.可执行程序(windows环境后缀为.exe)


2.2 数据文件

文件的内容不一定是程序,而是程序运行时读写的数据,


比如程序运行需要从中读取数据的文件,或者输出内容的文件。


2.3 文件名

一个文件有一个唯一的文件标识,


文件名包含3部分:文件路径+文件名主干+文件后缀,


例: c:\code\test.txt


3. 文件的打开和关闭

3.1 文件指针

在C语言中,我们需要知道的是 FILE* 是文件类型的指针,


他的具体实现是C语言已经帮我们实现了的。


3.2 文件的打开和关闭

文件的打开使用的是 fopen 函数:


文件的关闭使用的是 fclose 函数:


直接上代码:


例:


int main()
{
    //打开并读取这个文件名的文件
  FILE* pf = fopen("test.txt", "r");
    //判断打开文件是否成功
  if (pf == NULL)
  {
  perror("fopen");
  return 1;
  }
  //读文件
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


输出:

输出;fopen: No such file or directory


因为磁盘中并没有这个文件,所以报错。


对文件的操作还有很多:


文件使用方式 含义 如果指定文件不存在

“r”(只读) 为了输入数据,打开一个已经存在的文本文件 出错

“w”(只写) 为了输出数据,打开一个文本文件 建立一个新的文件

“a”(追加) 向文本文件尾添加数据 建立一个新的文件

“rb”(只读) 为了输入数据,打开一个二进制文件 出错

“wb”(只写) 为了输出数据,打开一个二进制文件 建立一个新的文件

“ab”(追加) 向一个二进制文件尾添加数据 出错

“r+”(读写) 为了读和写,打开一个文本文件 出错

“w+”(读写) 为了读和写,建议一个新的文件 建立一个新的文件

“a+”(读写) 打开一个文件,在文件尾进行读写 建立一个新的文件

“rb+”(读写) 为了读和写打开一个二进制文件 出错

“wb+”(读写) 为了读和写,新建一个新的二进制文件 建立一个新的文件

“ab+”(读写) 打开一个二进制文件,在文件尾进行读和写 建立一个新的文件

之后再用到的时候需要对其一定的了解。


4. 文件的顺序读写

接下来我们学习一些对文件读写的函数,


这样我们才能更好的操作文件。


功能       函数名          适用于

字符输入函数 fgetc       所有输入流

字符输出函数 fputc       所有输出流

文本行输入函数 fgets 所有输入流

文本行输出函数 fputs 所有输出流

格式化输入函数 fscanf 所有输入流

格式化输出函数 fprintf 所有输出流

二进制输入 fread 文件

二进制输出 fwrite 文件

我们通过一些例子来学习一下上述函数:


字符输出函数 fputc:



例1:


#include 
int main()
{
  FILE* pf = fopen("test.txt", "w");
  if (pf == NULL)
  {
  perror("fopen");
  return 1;
  }
  //写文件
  fputc('a', pf);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}

我们先通过 fputc 函数写了个字符‘a’进文件test.txt中。


打开文件:



文件中真的写入了字符‘a’。


字符输入函数 fgetc:


我们还能通过 fgetc 函数读文件验证一下:


#include 
int main()
{
  FILE* pf = fopen("test.txt", "r");
  if (pf == NULL)
  {
  perror("fopen");
  return 1;
  }
  //读文件
  int ch = fgetc(pf);
  printf("%c\n", ch);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}

输出:



我们发现真的读出并打印出了字符‘a’。


接下来我们学习一下 fputs 函数和 fgets 函数。


例:


#include 
int main()
{
  FILE* pf = fopen("test.txt", "w");
  if (pf == NULL)
  {
  perror("fopen");
  return 1;
  }
  //写文件
  fputs("welcome to my blog\n", pf);
  fputs("happy new year\n", pf);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}

输出:



写完文件之后,自然是读出来看看:



#include 
int main()
{
  FILE* pf = fopen("test.txt", "r");
  if (pf == NULL)
  {
  perror("fopen");
  return 1;
  }
  //读文件
  char buf[20] = { 0 };
  fgets(buf, 20, pf);//只读一行
  printf("%s\n", buf);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


我们发现 fgets 函数只读一行:



只要我们再用一次 fgets 函数就行:


#include 
int main()
{
  FILE* pf = fopen("test.txt", "r");
  if (pf == NULL)
  {
  perror("fopen");
  return 1;
  }
  //读文件
  char buf[20] = { 0 };
  fgets(buf, 20, pf);//只读一行
  printf("%s", buf);
  fgets(buf, 20, pf);
  printf("%s", buf);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}

输出:



接下来是 fprintf 函数,格式化写入文件:



例:


#include 
typedef struct S
{
  char name[20];
  int age;
  float score;
}S;
int main()
{
  S s = { "zhagnsan",120,2.22 };
  S* ps = &s;
  FILE* pf = fopen("test.txt", "w");
  if (pf == NULL)
  {
  perror("fopen");
  return 1;
  }
  //格式化写入文件
  fprintf(pf, "%s %d %f\n", ps->name, ps->age, ps->score);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}

输出:



文件成功写入了,


接下来是格式化输出 fscanf 函数:



例:

#include 
typedef struct S
{
  char name[20];
  int age;
  float score;
}S;
int main()
{
  S s = { "zhagnsan",120,2.22 };
  S* ps = &s;
  FILE* pf = fopen("test.txt", "r");
  if (pf == NULL)
  {
  perror("fopen");
  return 1;
  }
  //格式化的读文件
  fscanf(pf, "%s %d %f", ps->name, &(ps->age), &(ps->score));
  printf("%s %d %f\n", ps->name, ps->age, ps->score);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


输出:



最后是二进制写入文件 fwrite 函数:




#include 
typedef struct S
{
  char name[20];
  int age;
  float score;
}S;
int main()
{
  S s = { "zhagnsan",120,2.22 };
  S* ps = &s;
  FILE* pf = fopen("test.txt", "wb");
  if (pf == NULL)
  {
  perror("fopen");
  return 1;
  }
  //写文件
  fwrite(&s, sizeof(S), 1, pf);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


输出:



因为写进去的是二进制的形式,所以就出现了一些你看不懂的东西。


接着,我们用二进制的形式读取文件 fread 函数:


#include 
typedef struct S
{
  char name[20];
  int age;
  float score;
}S;
int main()
{
  S s = { "zhagnsan",120,2.22 };
  //S s = {0};
  S* ps = &s;
  FILE* pf = fopen("test.txt", "wb");
  if (pf == NULL)
  {
  perror("fopen");
  return 1;
  }
  //读文件
  fread(&s, sizeof(S), 1, pf);
  printf("%s %d %f", s.name, s.age, s.score);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}

输出:



成功打印出来。


4.1 对比一组函数

scanf / fscanf / sscanf


printf / fprintf / sprintf



例:


#include 
typedef struct S
{
  char name[20];
  int age;
  float score;
}S;
int main()
{
  S s = { "zhagnsan",120,2.22 };
  char buf[100] = { 0 };
  sprintf(buf, "%s %d %f", s.name, s.age, s.score);
  printf("%s\n", buf);
  S tmp;
  sscanf(buf, "%s %d %f", tmp.name, &(tmp.age), &(tmp.score));
  printf("%s %d %f", tmp.name, tmp.age, tmp.score);
  return 0;
}

输出:


输出:
zhagnsan 120 2.220000
zhagnsan 120 2.220000

5. 文件的随机读写

5.1 fseek

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


5.2 ftell

返回文件指针相对于起始位置的偏移量。(计算文件指针所在位置)


5.3 rewind

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


事先在文件中存储"abcdef"。


例:


#include 
int main()
{
  FILE* pf = fopen("test.txt", "r");
  if (pf == NULL)
  {
  perror("fopen");
  }
  else
  {
  int ch = fgetc(pf);
  printf("%c\n", ch);
  ch = fgetc(pf);
  printf("%c\n", ch);  
  ch = fgetc(pf);
  printf("%c\n", ch);
  fseek(pf, -2, SEEK_CUR);//文件指针偏移
  ch = fgetc(pf);//查看偏移量
  printf("%c\n", ch);
  rewind(pf);//文件指针返回起始位置
  printf("%d\n", ftell(pf));
  fclose(pf);
  pf = NULL;
  }
  return 0;
}


输出:


输出:
a
b
c
b
0

6. 文本文件和二进制文件

根据数据的组织形式,数据文件被称为文本文件或者二进制文件。


数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。


例:


#include 
int main()
{
  int a = 10000;
  FILE* pf = fopen("test.txt", "wb");
  fwrite(&a, 4, 1, pf);//二进制的形式写到文件中
  fclose(pf);
  pf = NULL;
  return 0;
}

然后再VS中打开这个文件:



然后就能看到:


我们存进内存的数以小端形式存储,


这里展现出的是以十六进制打印出来的结果,其本质就是二进制数。


7. 文件读取结束的判定

7.1 feof

这个函数是用于判断文件读取结束的原因:


如果文件是因为读取失败而结束就返回0,


如果文件是遇到文件尾结束就返回非0数。


8. 文件缓冲区

如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),


然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。


缓冲区的大小根据C编译系统决定的。


例:



如果缓冲区没满,主动刷新缓冲区也会将数组存入磁盘。


而C语言中调用 fclose 函数就会刷新一下,


所以,写程序如果打开了文件,记得一定要关闭,否则肯数据就丢失了。


写在最后:

以上就是本篇文章的内容了,感谢你的阅读。


如果喜欢本文的话,欢迎点赞和评论,写下你的见解。


如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。



相关文章
|
15天前
|
存储 C语言
C语言文件操作(2)
【10月更文挑战第2天】
|
13天前
|
程序员 编译器 C语言
C语言底层知识------文件操作
本文详细介绍了文件操作的基本概念,包括文件的分类(程序文件和数据文件,其中着重于数据文件的文本文件和二进制文件),流的概念及其在C程序中的应用,以及标准输入输出流stdin、stdout和stderr的作用。作者通过示例展示了如何使用fopen、fclose和常见的读写函数如fgetc、fputc和fgets进行文件操作。
14 2
|
1月前
|
C语言
C语言——文件操作
本文介绍了文件的基本操作,包括文件的打开、关闭、读取和写入。使用`fopen`函数以不同模式(如“r”、“w”等)打开文件,并通过`fclose`关闭。文章详细解释了如何利用`fputc`、`fputs`及`fprintf`进行格式化写入,同时介绍了`fgetc`、`fgets`和`fscanf`用于文件内容的读取。此外,还涵盖了二进制文件的读写方法以及如何通过`fseek`、`ftell`和`rewind`实现文件的随机访问。
44 1
C语言——文件操作
|
16天前
|
存储 缓存 编译器
文件操作——C语言
文件操作——C语言
|
6天前
|
存储 C语言
简述C语言文件操作
简述C语言文件操作
6 0
|
11天前
|
存储 文件存储 C语言
深入C语言:文件操作实现局外影响程序
深入C语言:文件操作实现局外影响程序
|
16天前
|
存储 程序员 编译器
C语言文件操作(1)
【10月更文挑战第1天】
|
16天前
|
存储 C语言
C语言的文件操作
C语言的文件操作
13 0
|
18天前
|
存储 移动开发 Unix
C 语言文件操作详解
C 语言文件操作详解
|
1月前
|
存储 C语言
C语言程序设计核心详解 第十章:位运算和c语言文件操作详解_文件操作函数
本文详细介绍了C语言中的位运算和文件操作。位运算包括按位与、或、异或、取反、左移和右移等六种运算符及其复合赋值运算符,每种运算符的功能和应用场景都有具体说明。文件操作部分则涵盖了文件的概念、分类、文件类型指针、文件的打开与关闭、读写操作及当前读写位置的调整等内容,提供了丰富的示例帮助理解。通过对本文的学习,读者可以全面掌握C语言中的位运算和文件处理技术。