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

C/C++文件操作/IO流

学习任务:

⭐认识文件。⭐学习C语言中文件如何打开和关闭。⭐学习C语言中文件的读写方法(包括顺序读写和随机读写)。⭐学习C语言文件操作中如何判断文件读取结束。⭐简单了解FILE缓冲区。⭐认识流。⭐学习C++的IO流,包括标准IO流和文件IO流,即C++的文件操作。⭐学习stringstream。

学习流程:

先对C语言的文件操作进行学习,然后带着建立在C语言文件操作的基础和C++基础上学习C++IO流。

1、认识文件

程序文件和数据文件

直接点 - 磁盘上的文件,就是文件。从文件功能的角度上,文件分有数据文件和程序文件。

程序文件包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程(windows环境后缀为.exe)。

数据文件的文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。

文件名

一个文件要有一个唯一的文件标识,以便用户识别和引用。文件名包含3部分:文件路径+文件名主干+文件后缀。

例如: c:\C++_code\test.txt

2、文件的打开和关闭

2.1 文件指针

在C语言的文件操作中,需要使用文件指针来对硬盘上的文件进行操作。每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名为FILE。

以下是FILE结构体的成员变量,不同编译器或许有不同的变量,但是大同小异。除此之外,FILE中会保存缓冲区、文件描述符等等。

//FILE
struct _iobuf {char* _ptr;int _cnt;char* _base;int _flag;int _file;int _charbuf;int _bufsiz;char* _tmpfname;
};
typedef struct _iobuf FILE;

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息。

FILE* f;//文件指针变量

定义f是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件,即通过文件指针变量能够找到与它关联的文件,就如上图一样,f指向了文件信息区。

2.2 文件的打开与关闭操作

对一个文件进行读写操作之前先打开该文件,操作完后需要关闭文件。在C语言中,使用fopen打开文件,使用fclose关闭文件。

//打开文件
FILE * fopen ( const char * filename, const char * mode );
参数:
filename:需要打开的文件的名字+路径(默认在当前文件路径中)
mode:打开文件的方式
返回值:返回一个文件指针//关闭文件
int fclose ( FILE * stream );
参数:文件指针,即需要关闭的那个文件的文件指针
返回值:成功返回0

文件的打开方式

文件使用方式含义如果指定文件不存在
“r”(只读)为了输入数据,打开一个已经存在的文本文件出错
“w”(只写)为了输出数据,打开一个文本文件建立一个新的文件
“a”(追加)向文本文件尾添加数据建立一个新的文件
“rb”(只读)为了输入数据,打开一个二进制文件出错
“wb”(只写)为了输出数据,打开一个二进制文件建立一个新的文件
“ab”(追加)向一个二进制文件尾添加数据出错
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建议一个新的文件建立一个新的文件
“a+”(读写)打开一个文件,在文件尾进行读写建立一个新的文件
“rb+”(读写)为了读和写打开一个二进制文件出错
“wb+”(读写)为了读和写,新建一个新的二进制文件建立一个新的文件
“ab+”(读写)打开一个二进制文件,在文件尾进行读和写建立一个新的文件

代码演示

int main()
{//打开文件FILE* pf = fopen("test.txt", "r");//只读方式打开if (pf == NULL){printf("%s\n", strerror(errno));return 1;}//读文件操作//.....//关闭文件fclose(pf);pf = NULL;return 0;
}

3、文件的顺序读写

对于文件的顺序读写,有以下函数需要学习去使用:

功能函数名适用于
字符输入函数fgetc所有输入流
字符输出函数fputc所有输出流
文本行输入函数fgets所有输入流
文本行输出函数fputs所有输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入fread文件
二进制输出fwrite文件

3.1 代码演示

3.1.1 fgetc和fputc函数

fputc函数+只写操作,写字符进去文件中,文件路径默认当前路径

int main()
{//打开文件FILE* pf = fopen("test.txt", "w");//只写方式打开if (pf == NULL){printf("%s\n", strerror(errno));return 1;}//写文件char i = 0;for (i = 'a'; i <= 'z'; ++i){fputc(i, pf);}//关闭文件fclose(pf);pf = NULL;return 0;
}

fgetc函数+只读操作:

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

 3.1.2 fgets和fputs函数

fputs函数+只写操作

//写一行数据
int main()
{FILE* pf = fopen("test.txt", "w");if (pf == NULL){printf("%s\n", strerror(errno));return 1;}//写一行数据fputs("hello bit\n", pf);fputs("hello bit\n", pf);//关闭文件fclose(pf);pf = NULL;return 0;
}

fgets函数+只读操作

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

 3.1.3 fsacnf和fprintf函数

fprintf函数+只写操作

struct S
{char arr[10];int age;float score;
};int main()
{struct S s = { "zhangsan", 25, 50.5f };FILE*pf = fopen("test.txt", "w");if (pf == NULL){perror("fopen");return 1;}//fprintf(pf, "%s %d %f", s.arr, s.age, s.score);fclose(pf);pf = NULL;return 0;
}

 fscanf函数+只读操作

int main()
{struct S s = {0};FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("fopen");return 1;}//将pf中的数据写到结构体对象s中fscanf(pf, "%s %d %f", s.arr, &(s.age), &(s.score));//打印//printf("%s %d %f\n", s.arr, s.age, s.score);fprintf(stdout, "%s %d %f\n", s.arr, s.age, s.score);fclose(pf);pf = NULL;return 0;
}

对于以上三对接口,都适用于所有输入或输出流,简单来说,不仅仅适用于文件流的读写,还可以是标准输入输出流,使用方法就是将文件指针改成以下三种流的名字即可。

任何一个C程序,只要运行起来就会默认打开3个流:

FILE* stdin - 标准输入流(键盘)

FILE* stdout - 标准输出流(屏幕)

FILE* stderr - 标准错误流(屏幕)

3.1.4 fread和fwrite函数

fread和fwrite是以二进制的形式进行读写,即保存在文件的数据是二进制的形式保存的。

fwrite函数+二进制只写操作

struct S
{char arr[10];int age;float score;
};int main()
{struct S s = { "zhangsan", 25, 50.5f };//以二进制的形式写到文件中FILE* pf = fopen("test.txt", "wb");if (pf == NULL){perror("fopen");return 1;}//二进制的方式写fwrite(&s, sizeof(struct S), 1, pf);fclose(pf);pf = NULL;return 0;
}

fread函数+二进制只读操作

int main()
{struct S s = { 0 };FILE* pf = fopen("test.txt", "rb");if (pf == NULL){perror("fopen");return 1;}//二进制的方式读fread(&s, sizeof(struct S), 1, pf);printf("%s %d %f\n", s.arr, s.age, s.score);fclose(pf);pf = NULL;return 0;
}

3.2 对比函数 

对比以下函数

scanf/fscanf/sscanf

 
printf/fprintf/sprintf

从上面的示例代码中我们已经知道,前两组的区别是:

scanf是针对标准输入格式化输入语句

printf是针对标准输出格式化输出语句

fscanf是针对所有输入流的格式化输入语句

fprintf是针对所有输出流的格式化输出语句

而对于sscanf和sprintf

sscanf是从字符串中读取格式化数据

 sprintf是将格式化数据写入字符串

struct S
{char arr[10];int age;float score;
};int main()
{struct S s = { "zhangsan", 20, 55.5f };struct S tmp = { 0 };char buf[100] = { 0 };//把s中的格式化数据转化成字符串放到buf中sprintf(buf, "%s %d %f", s.arr, s.age, s.score);//"zhangsan 20 55.500000";printf("字符串:%s\n", buf);//从字符串buf中获取一个格式化的数据到tmp中sscanf(buf, "%s %d %f", tmp.arr, &(tmp.age), &(tmp.score));printf("格式化:%s %d %f\n", tmp.arr, tmp.age, tmp.score);return 0;
}

这一对函数跟序列化与反序列化很相似。

文件的随机读写

文件的随机读写,有三个函数提供服务:fseek、ftell和rewind。

fseek函数:

int fseek ( FILE * stream, long int offset, int origin );
函数功能:根据文件指针的位置和偏移量来定位文件指针。
参数:
stream:文件指针
offset:偏移量
origin:从文件指针的位置

 origin参数:

SEEK_SET:文件的开头

SEEK_CUR:文件指针当前位置

SEEK_END:文件的末尾

#include <stdio.h>
int main()
{FILE* pFile;pFile = fopen("example.txt", "wb");fputs("This is an apple.", pFile);fseek(pFile, 9, SEEK_SET);fputs(" sam", pFile);fclose(pFile);return 0;
}

ftell函数

long int ftell ( FILE * stream );
函数功能:返回文件指针相对于起始位置的偏移量。

rewind函数

void rewind ( FILE * stream );
函数功能:让文件指针的位置回到文件的起始位置。

文本文件和二进制文件

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

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

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

文件读取结束的判断

feof函数

feof函数用来判断文件读取结束的原因是什么?是读取失败结束,还是遇到文件尾结束。

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

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

文件缓冲区

ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。

C++IO流 

流是什么

“流”即是流动的意思,是物质从一处向另一处流动的过程,是对一种有序连续且具有方向性的数据( 其单位可以是bit,byte,packet )的抽象描述。

C++流是指信息从外部输入设备(如键盘)向计算机内部(如内存)输入和从内存向外部输出设备(显示器)输出的过程。这种输入输出的过程被形象的比喻为“流”。它的特性是:有序连续、具有方向性。为了实现这种流动,C++定义了I/O标准类库,这些每个类都称为流/流类,用以完成某方面的功能。

C++系统实现了一个庞大的类库,其中ios为基类,其他类都是直接或间接派生自ios类。

 C++标准IO流

相关文章:

C/C++文件操作/IO流

学习任务&#xff1a; ⭐认识文件。⭐学习C语言中文件如何打开和关闭。⭐学习C语言中文件的读写方法&#xff08;包括顺序读写和随机读写&#xff09;。⭐学习C语言文件操作中如何判断文件读取结束。⭐简单了解FILE缓冲区。⭐认识流。⭐学习C的IO流&#xff0c;包括标准IO流和文…...

推荐 7 个超牛的 Spring Cloud 实战项目

个 把一个大型的单个应用程序和服务拆分为数个甚至数十个的支持微服务&#xff0c;这就是微服务架构的架构概念&#xff0c;通过将功能分解到各个离散的服务中以实现对解决方案的解耦。 关于微服务相关的学习资料不多&#xff0c;而 GitHub 上的开源项目可以作为你微服务之旅…...

Linux信号:信号 信号集 信号集函数

1. 信号的概念 Linux进程间通信的方式之一。信号也称为“软件中断”。 信号特点&#xff1a; 简单&#xff1b;携带信息有限&#xff1b;满足特定条件才发送信号&#xff1b;可进行用户空间和内核空间进程的交互&#xff1b; 信号4要素&#xff1a; &#xff08;1&#xf…...

详解八大排序算法-附动图和源码(插入,希尔,选择,堆排序,冒泡,快速,归并,计数)

目录 &#x1f34f;一.排序的概念及应用&#x1f34f; 1.排序的概念 2.排序的应用 3.常用的排序算法 &#x1f34e;二.排序算法的实现&#x1f34e; 1.插入排序 1.1直接插入排序 1.2希尔排序&#xff08;缩小增量排序&#xff09; 2.选择排序 2.1直接选择排序 2.2堆排序…...

网络编程--协议、协议族、地址族

写在前面 这里先介绍下socket函数&#xff08;Windows版本&#xff09;的函数声明&#xff0c;后续内容均围绕该声明展开&#xff1a; #include <winsock2.h> //af: 指定该套接字的协议族 //type: 指定该套接字的数据传输方式 //protocol: 指定该套接字的最终协议 //返…...

Linux入门操作

pwd 查看当前目录 与 自动补全 文件详情 drwxrwxr-x d代表文件夹 -代表文件 其中rwx rwx r-x r是可读 w是可写 x 执行 第一组&#xff08;前三个&#xff09;指文件拥有者的权限 第二组&#xff08;中三个&#xff09;代表文件拥有的组的权限 第三组&#xff08;后三个&am…...

1。C语言基础知识回顾

学习嵌入式的C基础知识&#xff0c;主要包括几个核心知识点&#xff1a;三大语法结构、常用的数据类型、函数、结构体、指针、文件操作。 一、顺序结构 程序自上而下依次执行、没有分支、代码简单。 常见顺序结构有&#xff1a;四则运算&#xff1a;&#xff0c;-&#xff0…...

学习如何通过构建一个简单的JavaScript颜色游戏来操作DOM

学习如何通过构建一个简单的JavaScript颜色游戏来操作DOM 题目要求 我们将构建一个简单的颜色猜谜游戏。每次游戏启动时&#xff0c;都会选择一个随机的RGB颜色代码。根据游戏模式&#xff0c;我们将在屏幕上提供三个&#xff08;简单&#xff09;或六个&#xff08;困难&…...

【算法学习】—n皇后问题(回溯法)

【算法学习】—n皇后问题(回溯法) 1. 什么是回溯法&#xff1f; 相信"迷宫"是许多人儿时的回忆&#xff0c;大家小时候一定都玩过迷宫游戏。我们从不用别人教&#xff0c;都知道走迷宫的策略是&#xff1a; 当遇到一个岔路口&#xff0c;会有以下两种情况&#xf…...

万亿OTA市场进入新爆发期,2025或迎中国汽车软件付费元年

伴随智能汽车市场规模发展&#xff0c;越来越多的汽车产品具备OTA能力&#xff0c;功能的优化、以及服务的差异化&#xff0c;成为了车企竞争的新战场。 例如&#xff0c;今年初&#xff0c;问界M5 EV迎来了首次OTA升级&#xff0c;升级内容覆盖用户在实际用车中的多个场景&am…...

Android硬件通信之 蓝牙Mesh通信

一&#xff0c;简介 蓝牙4.0以下称为传统蓝牙&#xff0c;4.0以上是低功耗蓝牙&#xff0c;5.0开始主打物联网 5.0协议蓝牙最重要的技术就是Mesh组网&#xff0c;实现1对多&#xff0c;多对多的无线通信。即从点对点传输发展为网络拓扑结构&#xff0c;主要领域如灯光控制等&…...

PG数据库实现bool自动转smallint的方式

删除函数&#xff1a; 语法&#xff1a; DROP FUNCTION IF EXISTS your_schema_name.function_name(arg_type1, arg_type2) CASCADE RESTRICT; 实例&#xff1a; DROP FUNCTION IF EXISTS platformyw.boolean_to_smallint(bool) CASCADE RESTRICT; 查询是否存在函数 语法: SELE…...

易观千帆 | 2023年3月证券APP月活跃用户规模盘点

易观&#xff1a;2023年3月证券服务应用活跃人数14131.58万人&#xff0c;相较上月&#xff0c;环比增长0.61%&#xff0c;同比增长0.60%&#xff1b;2023年3月自营类证券服务应用Top10 活跃人数6221.44万人&#xff0c;环比增长0.08%&#xff1b;2023年3月第三方证券服务应用T…...

2023年江苏专转本成绩查询步骤

2023年江苏专转本成绩查询时间 2023年江苏专转本成绩查询时间预计在5月初&#xff0c;参加考试的考生&#xff0c;可以关注考试院发布的消息。江苏专转本考生可在规定时间内在省教育考试院网&#xff0c;在查询中心页面中输入准考证号和身份证号进行查询&#xff0c;或者拨…...

JavaScript中sort()函数

sort()函数是javascript中自带函数&#xff0c;这个函数的功能是排序。 使用sort()函数时&#xff0c;函数参数如果不设置的话&#xff0c;以默认方式进行排序&#xff0c;就是以字母顺序进行排序&#xff0c;准确的讲就是按照字符编码的顺序进行排序。 var arr [3,2,3,34,1…...

泰克Tektronix DPO5204B混合信号示波器

特征 带宽&#xff1a;2 GHz输入通道&#xff1a;4采样率&#xff1a;1 或 2 个通道上为 5 GS/s、10 GS/s记录长度&#xff1a;所有 4 个通道 25M&#xff0c;50M&#xff1a;1 或 2 个通道上升时间&#xff1a;175 皮秒MultiView zoom™ 记录长度高达 250 兆点>250,000 wf…...

突破传统监测模式:业务状态监控HM的新思路

作者&#xff1a;京东保险 管顺利 一、传统监控系统的盲区&#xff0c;如何打造业务状态监控。 在系统架构设计中非常重要的一环是要做数据监控和数据最终一致性&#xff0c;关于一致性的补偿&#xff0c;已经由算法部的大佬总结过就不在赘述。这里主要讲如何去补偿&#xff…...

0Ω电阻在PCB板中的5大常见作用

在PCB板中&#xff0c;时常见到一些阻值为0Ω的电阻。我们都知道&#xff0c;在电路中&#xff0c;电阻的作用是阻碍电流&#xff0c;而0Ω电阻显然失去了这个作用。那它存在于PCB板中的原因是什么呢&#xff1f;今天我们一探究竟。 1、充当跳线 在电路中&#xff0c;0Ω电阻…...

分布式消息队列Kafka(三)- 服务节点Broker

1.Kafka Broker 工作流程 &#xff08;1&#xff09;zookeeper中存储的kafka信息 ​ 1&#xff09;启动 Zookeeper 客户端。 [zrclasshadoop102 zookeeper-3.5.7]$ bin/zkCli.sh ​ 2&#xff09;通过 ls 命令可以查看 kafka 相关信息。 [zk: localhost:2181(CONNECTED) 2]…...

蠕动泵说明书_RDB

RDB_2T-S蠕 动 泵 概述 蠕动灌装泵是一种高性能、高质量的泵。采用先进的微处理技术及通讯方式做成的控制器和步进电机驱动器&#xff0c;配以诚合最新研制出的泵头&#xff0c;使产品在稳定性、先进性和性价比上达到一个新的高度。适用饮料、保健品、制药、精细化工等诸流量…...

浅谈react如何自定义hooks

react 自定义 hooks 简介 一句话&#xff1a;使用自定义hooks可以将某些组件逻辑提取到可重用的函数中。 自定义hooks是一个从use开始的调用其他hooks的Javascript函数。 下面以一个案例: 新闻发布操作&#xff0c;来简单说一下react 自定义 hooks。 不使用自定义hooks时 …...

如何优雅的写个try catch的方式!

软件开发过程中&#xff0c;不可避免的是需要处理各种异常&#xff0c;就我自己来说&#xff0c;至少有一半以上的时间都是在处理各种异常情况&#xff0c;所以代码中就会出现大量的try {...} catch {...} finally {...} 代码块&#xff0c;不仅有大量的冗余代码&#xff0c;而…...

海尔智家:智慧场景掌握「主动」权,用户体验才有话语权

2023年1月&#xff0c;《福布斯》AI专栏作家Rob Toews发布了年度AI发展预测&#xff0c;指出人工智能的发展将带来涉及各行业、跨学科领域的深远影响。变革将至&#xff0c;全球已掀起生成式AI热&#xff0c;以自然语言处理为代表的人工智能技术在快速进化&#xff0c;积极拥抱…...

基于铜锁,在前端对登录密码进行加密,实现隐私数据保密性

本文将基于 铜锁&#xff08;tongsuo&#xff09;开源基础密码库实现前端对用户登录密码的加密&#xff0c;从而实现前端隐私数据的保密性。 首先&#xff0c;铜锁密码库是一个提供现代密码学算法和安全通信协议的开源基础密码库&#xff0c;在中国商用密码算法&#xff0c;例…...

LVS的小总结

LVS的工作模式及其工作过程&#xff1a; LVS 有三种负载均衡的模式&#xff0c;分别是VS/NAT&#xff08;nat 模式&#xff09;、VS/DR&#xff08;路由模式&#xff09;、VS/TUN&#xff08;隧道模式&#xff09;。 1、NAT模式&#xff08;NAT模式&#xff09; 原理&#x…...

Spring依赖注入(DI配置)

Spring依赖注入 1. 依赖注入方式【重点】1.1 依赖注入的两种方式1.2 setter方式注入问题导入引用类型简单类型 1.3 构造方式注入问题导入引用类型简单类型参数适配【了解】 1.4 依赖注入方式选择 2. 依赖自动装配【理解】问题导入2.1 自动装配概念2.2 自动装配类型依赖自动装配…...

绘声绘影2023简体中文版新功能介绍

会声会影是一款专业的数字音频工作站软件,它提供强大的音频编辑和制作功能,被广泛应用于音乐创作、录音棚录制以及现场演出等领域。会声会影的最新版本会声会影2023将于2022年底发布,主要功能和新功能详述如下: 会声会影2023主要功能: 1. 直观易用的界面:会声会影采用简洁而不…...

一个好的前端开发人员必须掌握的前端代码整洁与开发技巧

前端代码整洁与开发技巧 ​ 为保证前端人员在团队项目开发过程中的规范化、统一化&#xff0c;特建立《前端代码整洁与开发技巧》文档&#xff0c;通过代码简洁推荐、开发技巧推荐等章节来帮助我们统一代码规范和编码风格&#xff0c;从而提升项目的可读性和可维护性。 目录 …...

【别再困扰于LeetCode接雨水问题了 | 从暴力法=>动态规划=>单调栈】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…...

酒厂酒业IP网络广播系统建设方案-基于局域网的新一代交互智慧酒厂酒业IP广播设计指南

酒厂酒业IP网络广播系统建设方案-基于局域网的新一代交互智酒业酒厂IP广播系统设计指南 由北京海特伟业任洪卓发布于2023年4月25日 一、酒厂酒业IP网络广播系统建设需求 随着中国经济的快速稳步发展&#xff0c;中国白酒行业也迎来了黄金时期&#xff0c;产品规模、销售业绩等…...