C++文件操作(1)

C++文件操作

  • 1.文本的写入及读取
    • 文本文件写入
    • 文本文件读取
  • 2.二进制文件的写入及读取
    • 二进制文件写入
    • 二进制文件读取
  • 3.小结

C++也有处理文件的能力,其功能实现依赖文件流。文件流是C++中用来处理文件输入输出的一种流类。文件流可以用于从文件中读取数据或将数据写入到文件中。C++中的文件流类包括ifstream(用于从文件中读取数据)、ofstream(用于向文件中写入数据)和fstream(用于同时读取和写入文件)。这些文件流类提供了一组成员函数,可以用来打开、关闭、读取和写入文件。使用文件流可以方便地进行文件操作,如读取文件内容、写入数据到文件中等。这里我们主要学习文件的处理方法,想要深度了解文件流的小伙伴可以在学完本节之后再补充相关知识。

1.文本的写入及读取

字符串文件是C++经常处理的一种文件类型,其依赖为i/ostream和fstream类。

文本文件写入

我们看一个向文件中写入内容的例子:

#include<stdio.h>#include<iostream>
#include<fstream>#include <string>
using std::string;
using namespace std;
int main()
{string filename="test.txt"; // 文件名ofstream mytest; // 使用ofstream创建文件输出流对象,名字自拟mytest.open(filename); // 打开文件// 向文件中写入数据mytest<<"这是一个测试\n"<<"我们尝试连续输入内容\n";mytest<<"继续测试";// 关闭文件mytest.close();
}

在这段代码中,filename定义了一个文件名,我们尝试使用文件流打开文件,当当前路径下存在文件时,这段代码会截断文件,即打开文件后删除文件内容,重新进行写入操作,当文件不存在时,会在当前路径下创建文件并写入内容。运行这段代码会在.cpp文件路径下产生一个.txt文件:
在这里插入图片描述
虽然操作成功了,但是这样的做法存在不足和风险,比如我们在打开或创建文件时应当给出文件的确切位置,不应该只让它生成在.cpp文件的路径下;在使用文件之前应当判断文件是否成功打开。
为了解决以上不足,我们先详细了解一下ofstream输出流。ofstream创建了文件输出流对象,而open函数可以带有两个参数,即文件及路径和打开方式。文件的绝对路径有以下写法:

R"(C:\data…\test.txt)" (C++11标准)
“C:\data\…\text.txt”
“C:/data/…/text.txt”

其次,文件的打开方式可以这样规定:

ios::out 截断文件内容打开文件,为参数默认值
ios::truck 截断文件内容,类似于ios::out
ios::app 在文件后添加内容

我们再来测试一下:

int main()
{ofstream mytest;mytest.open("E:\\c++\\class3start11\\test.txt",ios::app);// 使用ios::app 在文件后添加内容// 向文件中写入数据mytest<<"这是一个测试\n"<<"我们尝试连续输入内容\n";// 关闭文件mytest.close();
}

再打开文件其内容就变成了:
在这里插入图片描述
此外,文件也不是一定能打开文件的情况,通常情况下无法正常打开文件的情况有:

1.目录不存在
2.磁盘空间已满
3.没有权限(linux系统下常见)

应对这种情况,我们可以使用mytest.is_open()来判断文件是否成功打开:

int main()
{ofstream mytest("test.txt",ios::app); // 在创建文件输出流对象时直接提供路径和打开方式参数,// 不需要再使用open进行打开if(mytest.is_open()) // 判断文件是否成功打开{mytest<<"这是一个测试\n"<<"我们尝试连续输入内容\n";// 关闭文件mytest.close();return 0;}else{cout<<"打开文件失败"<<endl;return 0;}
}

作为演示内容,我们就不写完整路径了。

文本文件读取

读取文本文件内容需要用ifstream输出流进行操作,其参数也是两个,文件名和打开方式。打开方式只能使用使用in:

int main()
{// 读取文件参数只有iOS::inifstream mytest("test.txt",ios::in); // 用输入流打开文件,读取文件内容if(mytest.is_open()){cout<<"打开文件成功"<<endl;return 0;}
}

而后就要读取文件内容了。读取文件内容使用函数getline。getline函数有两个参数,即输出流对象和用于存储读取信息的变量。getline会按行读取文件内容,并返回是否读取成功。它很多重载,但常用的主要有两种方式:

if(mytest.is_open())
{string out; // 定义字符串类型out用于接收文件内容while(getline(mytest,out)) // 将当前行内容存入out,当前行没有内容时返回值为false{cout<<out<<endl;  }// 关闭文件mytest.close();
}
else
{cout<<"打开文件失败!"<<endl;
}

这样就可以在终端看到执行效果:
在这里插入图片描述
当然,这种用法还有一种比较简单的变种:

int main()
{// 读取文件参数只有iOS::inifstream mytest("test.txt",ios::in);// 打开文件失败的原因:1.文件不存在2.目录不存在3.没有权限if(mytest.is_open()){string out;while(mytest>>out){cout<<out<<endl;  }// 关闭文件mytest.close();}else{cout<<"打开文件失败"<<endl;return 0;}
}

这种方式使用起来更简单,我们记住就好。
另外,使用C风格字符串也可以接收文件内容,需要用到另一个getline函数的重载:

int main()
{ifstream mytest; mytest.open("test.txt",ios::in)if(mytest.is_open()){char out[21]; // 三个字符存储一个汉字// 读取文件一般要用getline函数一行一行读while(mytest.getline(out,20)) // getline的一个重载,第一个参数为记录文件内容的字符串名,第二个参数是这个字符串最大下标// 如果字符数组不能够存下某行数据,会在对应处直接终止运行退出程序。{cout<<out<<endl;}}else{cout<<"打开文件失败"<<endl;return 0;}// 关闭文件mytest.close();
}

这个例子中,我们使用的C类型字符串最多可以存储的汉字只有7个,当遇到一行超过7个汉字的情况,会立刻终止运行,但不会报错。如果我们扩大数组的大小(由于换行符的存在,这里至少需要设置成31)就可以完整读取了。但实际中如果遇到这种情况并不好处理,在不知道文本内容的时候,设置足够大的字符数组较难做到,况且如果字符数组设置过大,又会浪费空间,因此这种用法并不推荐。

2.二进制文件的写入及读取

文本文件的读写方便实用,其特点为每个字符都有实际意义,但只能用于处理字符串类型。在实际使用中,很多时候我们需要存取更复杂的类型,比如结构体、整形、图片等,这些内容用字符串处理并不方便。计算机的世界里,只有0和1两个数字,任何数据本质上都是由二进制数描述的,因此如果我们使用二进制对文件进行存取,理论上就可以处理所有文件和数据。C++也为我们提供了这样的存取方法。

二进制文件写入

使用二进制处理文件首先也是要用ofstream创建输出流对象,打开文件时也要额外说明使用二进制方式打开。写入的过程需要使用write函数,具体使用方法示例如下:

// 定义一个需要记录数据的基本结构,也可以使用自定义类或C++基本数据类型
struct Student
{char name[32];int age;char sex;
};
int main()
{ofstream mytest("test.doc",ios::binary);// 需要再打开方式后面加上binary用于告诉计算机使用二进制方式打开// 这里的ios::out可以省略if(mytest.is_open()){Student child={"ZhangSan",15,'m'}; // // 写入文件需要使用write函数mytest.write((const char*)&child,sizeof(Student));child=Student{"LiSi",20,'m'}; // 重载child,因为child变量之前已经赋值,因此不能直接初始化mytest.write((const char*)&child,sizeof(Student)); // 参数为需写入内容的地址(C++要求使用const char*),需写入内容的大小}else{cout<<"打开文件失败"<<endl;return 0;}// 关闭文件mytest.close();
}

这样我们就可以得到一个doc文件了:
在这里插入图片描述
但是它的内容是乱码的,这是因为二进制存储文件是按字节有效的,如果我们不知道存储的方式,是不能够正确解码的。

二进制文件读取

当我们知道数据的具体存储方式时,就可以编写程序查看存储的实际内容了。上例中,我们知道test.doc文件存储的数据是Student结构体,也就可以对它进行解码并查看内容了:

int main()
{ifstream mytest("test.doc",ios::in|ios::binary); // 读取二进制文件if(mytest.is_open()){// 二进制文件打开后需要用正确的接收格式接收Student child;// 二进制文件以数据类型的方式组织数据,没有换行的说法// mytest.read((char*)&ZhangSan,sizeof(Student)) 一次只能读取一个结构体数据while(mytest.read((char*)&child,sizeof(Student))){cout<<child.name<<" "<<child.age<<" "<<child.sex<<endl;}}else{cout<<"打开文件失败"<<endl;return 0;}// 关闭文件mytest.close();
}
// 输出为:ZhangSan 15 m
//        LiSi 20 m

这里需要注意几点问题:
1.由于C++中string类型内存布局具有不确定性,因此可能会影响二进制文件的读取,建议使用字符数组存储字符串;
2.一个结构体变量只能初始化一次,想要修改变量内容可以使用赋值或重载的方式;
3.C++处理文本文件时以换行符作为读取内容分隔符,getline函数也是在读取到第一个换行符时返回。二进制文件中换行符只被视为二进制数据,文件读取时以数据块作为分隔。

3.小结

这节主要介绍了C++处理文本文件和二进制文件的部分方法,由于篇幅原因,我们只提到了较为常见的函数和用法。后面的学习中我会继续对文件操作进行补充。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/657686.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《游戏-03_2D-开发》

基于《游戏-02_2D-开发》&#xff0c; 继续制作游戏&#xff1a; 首先要做的时切割人物Idle空闲状态下的动画&#xff0c; 在切割之前我们需要创建一个文件夹&#xff0c;用来存放动画控制器AnimatorContoller&#xff0c; 再创建一个人物控制器文件夹用来存放人物控制器&…

【Ubuntu 22.04.3 LTS】apt-get下载安装有关问题可能原因及解决方法

ubuntu 22.04.3 LTS unaccountably error 装啥啥没依赖 可能是用了不合适的源&#xff0c;换个就好了 Now, let’s take a look at the lsb_release output, with a special focus on the Codename, which could be a crucial piece of information. The lsb_release comm…

认识BPMN2.0

&#x1f496;专栏简介 ✔️本专栏将从Camunda(卡蒙达) 7中的关键概念到实现中国式工作流相关功能。 ✔️文章中只包含演示核心代码及测试数据&#xff0c;完整代码可查看作者的开源项目snail-camunda ✔️请给snail-camunda 点颗星吧&#x1f618; &#x1f496;说在前面 …

STM32单片机基本原理与应用(四)

直流电机驱动控制原理 1、电机正反转控制 在STM32中&#xff0c;直流电机的正反转控制主要通过改变电机输入电源的极性来实现。当电机的电压极性发生变化时&#xff0c;电机的旋转方向也会相应改变。在硬件电路中&#xff0c;可以通过继电器或晶体管等电子开关来切换电机的电源…

查找二叉树(tree_a)

时间限制&#xff1a;1秒 内存限制&#xff1a;128M 题目描述 已知一棵二叉树用邻接表结构存储&#xff0c;中序查找二叉树中值为x的结点&#xff08;x在二叉树中是唯一的&#xff09;&#xff0c;并指出是第几个结点。 输入描述 第一行n为二叉树的结点个树&#xf…

【TCP】重传与超时机制

前言 在网络通信的世界里&#xff0c;传输控制协议&#xff08;TCP&#xff09;扮演着一个至关重要的角色。它确保了数据的可靠传输&#xff0c;就像邮差确保每一封信都能准确无误地送达收件人手中一样。但是&#xff0c;网络环境充满了不确定性&#xff0c;数据包可能会因为各…

新书速览|Docker与Kubernetes容器运维实战

帮助读者用最短的时间掌握Docker与K8s运维技能 内容简介 随着云计算和容器技术的发展&#xff0c;Docker与Kubernetes已经成为各个企业首选的部署工具&#xff0c;使用它们可以提高系统的部署效率和运维能力&#xff0c;降低运维成本。本书是一本为初学者量身定制的Docker与Kub…

Android PMS——PMS服务启动流程(二)

PackageManagerService 既然是系统服务&#xff0c;那么肯定是通过 SystemServer 启动的&#xff0c;所以我们首先看一下 SystemServer 服务中启动 PackageManagerService 相关代码。 一、PMS启动 1、SystemServer 源码路径&#xff1a;/frameworks/base/services/java/com/…

iPhone手电筒不能工作的几种修复办法,总有一种适合你

这篇文章解释了为什么你的iPhone的手电筒不工作以及如何修复它。 手电筒不工作的原因 iPhone手电筒功能可能不起作用的原因有几个。通常&#xff0c;软件错误或小故障会导致该功能出现故障&#xff0c;但可能是你处于错误的电源模式或只需要充电。其他时候&#xff0c;确切的…

STM32F407移植OpenHarmony笔记4

上一篇写到make menuconfig报错&#xff0c;继续开整。 make menuconfig需要/device/soc/*下面有对应的Kconfig文件。 直接去gitee下载stm32的配置文件拿来参考用。 先提取Kconfig文件&#xff0c;后面再添加其它文件。https://gitee.com/openharmony/device_soc_st/tree/Open…

arcgis 如何将线路转为路面

在出外业的时候&#xff0c;用手机软件测出来的路&#xff08;线要素&#xff09;&#xff0c;需要转换成路面。具体操作如下&#xff1a; 1.打开线图层 2.菜单-地理处理-缓冲区 在缓冲区中&#xff0c;输入要转换的线要素&#xff0c;在线性单位下方填写要转换的面的宽度&am…

[E模拟] lc2670. 找出不同元素数目差数组(哈希表+状态压缩)

文章目录 1. 题目来源2. 题目解析 1. 题目来源 链接&#xff1a;2670. 找出不同元素数目差数组 2. 题目解析 哈希计数统计就行了&#xff0c;题解里有看到用 long 64 位进行状态压缩的&#xff0c;可以参考下。这类题就不纠结写法了。 思路&#xff1a; 两个哈希表&#x…

回响科技二面面试题解答

面试题 1、你们的数仓中DWD层为什么要划分数据域&#xff1f;划分数据域之后会对ADS层造成什么影响&#xff1f;是可以提效还是可扩展性强&#xff1f;你们是如何考虑的呢&#xff1f; 2、AZkaban和dolphinScheduler的区别是什么&#xff1f;如果选型会从哪几个方面来考虑呢&a…

《Numpy 简易速速上手小册》第10章:Numpy案例研究和实践技巧(2024 最新版)

文章目录 10.1 实际案例分析10.1.1 基础知识10.1.2 完整案例&#xff1a;天气数据分析10.1.3 拓展案例 1&#xff1a;股票价格分析10.1.4 拓展案例 2&#xff1a;信号处理 10.2 Numpy 最佳实践10.2.1 基础知识10.2.2 完整案例&#xff1a;高效数组操作10.2.3 拓展案例 1&#x…

vue-cli初始化项目很慢?

第一种情况 大部分是由于npm的镜像源不是淘宝的 cmd输入npm config get registry查看是不是淘宝的&#xff0c;是的话看第二种情况试试不是的话输入npm config set registry https://registry.npm.taobao.org 第二种情况 vue-cli配置文件不是使用淘宝镜像源的 找到文件.vue…

已实现:vue、h5项目如何使用echarts实现雷达图、六边形图表

说实话&#xff0c;要说图表里&#xff0c;最强的应该属于echarts了&#xff0c;不管是接入难度上&#xff0c;还是样式多样性上&#xff0c;还有社区庞大程度上&#xff0c;都是首屈一指的&#xff0c;反观有的人习惯用chart.js了&#xff0c;这个无可厚非&#xff0c;但是如果…

从C向C++5——友元和string

一.对象特性&#xff08;续&#xff09; 1.空指针访问成员函数 C中空指针也是可以调用成员函数的&#xff0c;但是也要注意有没有用到this指针。 如果用到this指针&#xff0c;需要加以判断保证代码的健壮性。 如果调用的成员函数不访问成员属性&#xff0c;那么空指针可以调…

C语言中大小写字母的转化

在C语言中&#xff0c;大小写字母的转化是一个非常基础且常用的功能。C语言中的字符是以ASCII码的形式存储的&#xff0c;而ASCII码中&#xff0c;小写字母和大写字母之间相差32。因此&#xff0c;可以通过简单的数学运算来实现大小写字母的转换。 一、数学运算转化 大写字母…

微信小程序如何实现实时显示输入内容

如下所示&#xff0c;在许多场景中需要实时显示用户输入&#xff0c;具体实现见下文。 .wxml <input type"text" placeholder"请输入{{item.value}}(必填)" style"width:80%;" bindinput"get_required_value" data-info"{{it…

科技云报道:新趋势下,国产数据库或“春山可望”

科技云报道原创。 从540亿元到1286亿元——这是中国通信标准化协会大数据技术标准推进委员会针对中国数据库行业给出的一份预测报告。 报告指出&#xff0c;未来五年&#xff0c;中国数据库行业将从百亿级市场跨越成为千亿级市场。 最近两年&#xff0c;中国的数据库行业似乎…