当前位置: 首页 > news >正文

C语言学习笔记——文件

目录

  • 1 文件的概念
  • 2 程序文件和数据文件
  • 3 二进制文件和文本文件
  • 4 流
    • 4.1 流的概念
    • 4.2 标准流
  • 5 文件信息区和文件指针
  • 6 处理文件的库函数
    • 6.1 fopen
    • 6.2 fclose
    • 6.3 fgetc
    • 6.4 fputc
    • 6.5 fgets
    • 6.6 fputs
    • 6.7 fscanf
    • 6.8 fprintf
    • 6.9 fread
    • 6.10 fwrite
    • 6.11 fseek
    • 6.12 ftell
    • 6.13 rewind
    • 6.14 feof 和 ferror
  • 7 文件缓冲区

1 文件的概念

在磁盘中,用于保存数据的工具就是文件
比如,下图的 test.txt 就是一个文件,保存了 1 2 3 4 5 6 7 8 9 10 这样的数据
在这里插入图片描述
在这里插入图片描述

2 程序文件和数据文件

从程序设计的角度上来说,文件主要分为程序文件和数据文件
程序文件:用于保存程序代码的文件,比如.c后缀的源文件,.h后缀的头文件
数据文件:用于保存其它数据的文件,比如上文提到的 test.txt 文件

3 二进制文件和文本文件

在C语言编程中,对文件进行操作时,主要有二进制文件和文本文件两个对象,它们都属于数据文件
文本文件:数据在保存到文件时,会先将该数据按字节为单位转换为字符,再以ASCII码的形式保存
二进制文件:数据在保存到文件时,会直接以二进制序列的形式保存

举例:1000在文本文件和二进制文件中的不同保存形式

在这里插入图片描述

4 流

4.1 流的概念

由于计算机在运行时,会与各种各样的外部设备交流,所以这会使得程序员需要掌握这些设备的输入输出方式,对程序员的要求大大提高,为避免这种现象的发生,提出了流的概念,流向程序员提供了一种便捷的输入输出方式,程序员只需要通过流,就可以直接与外部设备进行交互,不需要关心具体输入输出的细节

在这里插入图片描述

4.2 标准流

标准流主要有3个,分别是 stdin,stdout,stderr
stdin:标准输入流,用来从键盘上读取数据,scanf 所使用的流就是它
stdout:标准输出流,用来向屏幕输出数据,printf 所使用的流就是它
stderr:标准错误流,用来在屏幕上显示错误信息

C语言的程序启动时,默认就开启了这三个流

5 文件信息区和文件指针

打开文件时,会在内存中生成一个文件信息区,文件信息区本质是一个结构体(名为FILE),保存了文件的各种信息
用户可以通过指向文件信息区的文件指针来访问对应的文件,文件指针的类型为FILE*
在这里插入图片描述

6 处理文件的库函数

6.1 fopen

fopen 的函数声明如下:

FILE* fopen (const char* filename, const char* mode);

功能
打开一个文件

参数
filename 指要打开的文件的名称
mode 指文件的打开方式

返回值
若文件打开成功,则会返回指向该文件文件信息区的文件指针
若文件打开失败,则会返回空指针

文件的打开方式

功能文件不存在时
“r”指定本次打开要进行 读文件 操作,对象为文本文件出错
“w”指定本次打开要进行 写文件 操作并清空文件数据,对象为文本文件创建新文件
“a”在文件末尾添加新内容,对象为文本文件创建新文件
“rb”指定本次打开要进行 读文件 操作,对象为二进制文件出错
“wb”指定本次打开要进行 读文件 操作,对象为二进制文件创建新文件
“ab”在文件末尾添加新内容,对象为二进制文件创建新文件
“r+”指定本次打开要进行 读文件和写文件 操作,对象为文本文件出错
“w+”指定本次打开要进行 读文件和写文件 操作,对象为文本文件创建新文件
“a+”在文件末尾添加新内容,对象为文本文件创建新文件
“rb+”指定本次打开要进行 读文件和写文件 操作,对象为二进制文件出错
“wb+”指定本次打开要进行 读文件和写文件 操作,对象为二进制文件创建新文件
“ab+”在文件末尾添加新内容,对象为二进制文件创建新文件

举例:以读的形式,打开一个名为 “test.txt” 的文本文件

#include <stdio.h>
int main()
{FILE* pf = fopen("test.txt", "r"); //以读的方式打开文件if (pf == NULL) //防止使用空指针assert(pf);fclose(pf); //关闭文件pf = NULL;return 0;
}

6.2 fclose

int fclose ( FILE * stream );

功能
用于关闭打开的文件

参数
stream 为指向要关闭文件的文件指针

6.3 fgetc

int fgetc ( FILE * stream );

功能
用来从文件中获取一个字符

参数
stream 为指向要读取文件的文件指针

返回值
若读取成功,返回读取到的字符
若读取失败或者遇到文件末尾,返回EOF

举例:从文件中读取一个字符并输出

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL)assert(pf);printf("%c", (char)fgetc(pf));fclose(pf);pf = NULL;return 0;
}

6.4 fputc

int fputc ( int character, FILE * stream );

功能
用来向文件中写入字符

参数
character 为要写入的字符
stream 为指向要操作的文件的文件指针

返回值
若操作成功,则返回写入的字符
若操作失败,则返回EOF

举例:写一个字符到文件内

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "w");if (pf == NULL)assert(pf);fputc('a', pf);fclose(pf);pf = NULL;return 0;
}

6.5 fgets

char * fgets ( char * str, int num, FILE * stream );

功能
用来从文件中读出 num-1 个字符,放入 str 指向的字符串内,最后自动补 ‘\0’

参数
str 为指向存放字符的字符串的指针
num 为要读的字符数量,实际读取数量为 num-1
stream 为指向要读的文件的文件指针

返回值
若操作成功,则返回存放读取字符的字符串首地址
若操作失败,则返回空指针

举例:读取文件中的 4 个字符到字符串内

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL)assert(pf);char str[5] = " ";fgets(str, 5, pf);fclose(pf);pf = NULL;return 0;
}

6.6 fputs

int fputs ( const char * str, FILE * stream );

功能
将字符串的内容写到文件中

参数
str 为指向字符串的指针
stream 为指向要写的文件的指针

返回值
操作成功时,返回非负值
操作失败时,返回EOF

举例:读取一个字符串到文件内

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "w");if (pf == NULL)assert(pf);char str[20] = "hello world";fputs(str, pf);fclose(pf);pf = NULL;return 0;
}

6.7 fscanf

int fscanf ( FILE * stream, const char * format, parameterList );

功能
根据给出的格式,从文件中读取内容到后方的变量中

参数
stream 为指向要读的文件的文件指针
format 为需要用户指定的格式,比如%d,%s等
paramterList 为要存放数据的变量,可以有1个或多个

返回值
返回成功读取的数据的量
如果在读取的中途出错或遇到文件尾,会设置 ferror 或 feof 指示器
如果一个数据都没有读取成功,返回EOF

举例:读取文件中的数据到变量中

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "w");if (pf == NULL)assert(pf);char str[20] = " ";fscanf(pf, "%s", str);fclose(pf);pf = NULL;return 0;
}

6.8 fprintf

int fprintf ( FILE * stream, const char * format, parameterList);

功能
根据给出的格式,将对应变量中的值写入文件中

参数
stream 为指向要写的文件的指针
format 为需要用户指定的格式,比如%d,%s等
paramterList 为要读取的变量,可以有1个或多个

返回值
操作成功,则返回成功写入的字符的数量
操作失败,返回负数

举例:写入数据到文件中

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "w");if (pf == NULL)assert(pf);char str[20] = "hello world";printf("%d", fprintf(pf, "%s", str));fclose(pf);pf = NULL;return 0;
}

6.9 fread

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

功能
从文件中读取 count 个 size 大小的数据到 ptr 指向的空间内,但是是以二进制的形式进行读取

参数
ptr 为指向最终存放数据的空间的指针
size 是读取的每个元素的大小,单位为字节
count 是读取的元素个数
stream 是指向要读取的文件的文件指针

返回值
返回成功读取的元素的个数

举例:从文件中读取5个4字节的数据至数组中

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "rb");if (pf == NULL)assert(pf);int arr[5] = { 0 };fread(arr, sizeof(int), 5, pf);fclose(pf);pf = NULL;return 0;
}

6.10 fwrite

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

功能
从 ptr 指向的空间内读取 count 个 size 大小的数据并以二进制的形式写到文件内,

参数
ptr 为指向要读取的空间的指针
size 每个元素的大小
count 为元素的个数
stream 为指向要写入数据的文件的指针

返回值
返回成功写入的元素的个数

举例:向文件中写入5个4字节的数据

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "wb");if (pf == NULL)assert(pf);int arr[5] = { 1,2,3,4,5 };fwrite(arr, sizeof(int), 5, pf);fclose(pf);pf = NULL;return 0;
}

6.11 fseek

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

功能
通过文件指针的位置,偏移量来移动文件指针

参数
stream 是指向文件的文件指针
offset 是偏移量,用来计算新的文件指针位置
origin 是文件指针的位置,有以下三个取值

取值含义
SEEK_SET文件的起始位置
SEEK_CUR当前文件指针的位置
SEEK_END文件的末尾

返回值
操作成功,返回0
操作失败,返回非0

举例:读取下面这个文件的d字符
在这里插入图片描述

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL)assert(pf);fseek(pf, 3, SEEK_CUR);printf("%c", fgetc(pf));fclose(pf);pf = NULL;return 0;
}

图解:
在这里插入图片描述
注意事项
若 origin 取值为 SEEK_END ,则偏移量需要给入负数,才能读取前面的值

6.12 ftell

long int ftell ( FILE * stream );

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

参数
stream 为指向文件的文件指针

返回值
成功返回当前文件指针的位置
错误返回 -1L

举例:计算下面文件的文件尾相对于起始位置的偏移量
在这里插入图片描述

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL)assert(pf);while (fgetc(pf) != EOF); //使文件指针遍历到结尾printf("%d", ftell(pf));fclose(pf);pf = NULL;return 0;
}

图解:
在这里插入图片描述

6.13 rewind

void rewind ( FILE * stream );

功能
将文件指针重置到文件的开始位置

参数
stream 为指向文件的文件指针

返回值

举例:输出两次下列文件的内容
在这里插入图片描述

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL)assert(pf);char ch = 0;while ((ch = fgetc(pf)) != EOF){printf("%c ", ch);}printf("\n", ch);rewind(pf); //重置文件指针的位置while ((ch = fgetc(pf)) != EOF){printf("%c ", ch);}fclose(pf);pf = NULL;return 0;
}

6.14 feof 和 ferror

int feof ( FILE * stream );

功能
判断文件的读取是否因为遇到了文件尾而结束

参数
stream 为指向文件的文件指针

返回值
是遇到了文件尾而结束,则返回非0
不是则返回0

int ferror ( FILE * stream );

功能
判断文件的读取是否因为遇到了错误而结束

参数
stream 为指向文件的文件指针

返回值
是遇到了错误而结束则返回非0
不是则返回0

我们可以通过使用 feof 和 ferror 来让文件的读取更加安全

#include <stdio.h>
#include <assert.h>
int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL)assert(pf);char ch = 0;while ((ch = fgetc(pf)) != EOF){printf("%c ", ch);}if (feof(pf)){printf("遇到文件尾结束");}else if (ferror(pf)){perror("fault");}fclose(pf);pf = NULL;return 0;
}

7 文件缓冲区

计算机在从文件内读取数据或向文件内写入数据时,会先将数据存入输入/输出缓冲区,待输入/输出缓冲区被填满时,才会将数据读入计算机或输入到文件内,如果没有缓冲区的话,那么就会出现输入/输出一次数据,操作系统就要介入进行处理的情况,操作系统不断被打断,无法服务于其它的进程,会使得操作系统的效率降低
在这里插入图片描述

http://www.dtcms.com/a/320276.html

相关文章:

  • 基于Python的实习僧招聘数据采集与可视化分析,使用matplotlib进行可视化
  • iptables封堵实验
  • Java——详解形参实参方法的重载
  • 《C语言》函数练习题--3
  • (易视宝)易视TV is-E4-G-全志A20芯片-安卓4-烧写卡刷工具及教程
  • Docker国内可用镜像列表(长期免费)
  • 三重移相的TPS双有源桥(DAB)变换器【simulink仿真模型】
  • python见缝插针小游戏源码。(可复制)
  • 【tips】css模仿矢量图透明背景
  • 目前常用于视频会议的视频编码上行/下行带宽对比
  • mysql_mcp_server_pro源码部署及启动报错新手指南:让智能体长出手来直接获取到最底层的数据
  • AI应用案例全景分析:从理论到实践
  • dmctlcvt工具介绍数据文件路径变化后如何拉起数据库
  • 基于 FreeMarker 实现 SQL 模板动态生成的完整指南
  • 移动端项目框架推荐
  • Effective C++ 条款27: 尽量用const、enum、inline替换 #define
  • restTemplate禁用url编码
  • 安装mkdocs
  • Python从入门到精通——第六章 字典与集合
  • 「日拱一码」046 分支定界算法
  • Airflow 入门案例教程
  • 前端性能优化:从请求到资源的精细调控
  • 【第9话:感知算法基础1】深度学习神经网络模型基础知识概念入门简介
  • 批量获取亚马逊商品SKU商品规格调用流程
  • 【实时Linux实战系列】基于实时Linux的高频交易系统构建
  • Python 常用内置高阶函数
  • RabbitMQ面试精讲 Day 15:RabbitMQ故障转移与数据恢复
  • C++ min循环超超超详细指南
  • WFP DNS 域名解析
  • 深入理解C++模板进阶:非类型参数、特化与分离编译