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.rhkb.cn/news/250639.html

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

相关文章

ctfshow web-77

开启环境: 先直接用伪协议获取 flag 位置。 c?><?php $anew DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString(). );} exit(0); ?> 发现 flag36x.txt 文件。同时根目录下还有 readflag&#xff0c;估计需要调用 readflag 获…

RabbitMQ之三种队列之间的区别及如何选型

目录 不同队列之间的区别 Classic经典队列 Quorum仲裁队列 Stream流式队列 如何使用不同类型的队列​ Quorum队列 Stream队列 不同队列之间的区别 Classic经典队列 这是RabbitMQ最为经典的队列类型。在单机环境中&#xff0c;拥有比较高的消息可靠性。 经典队列可以选…

FFMPEG 之 DXVA2 硬解

一&#xff1a;FFMPEG 支持的硬解方式有很多&#xff1a; DXVA2、D3D11VA、CUDA、QSV、OPENCL、DRM、VAAPI、VDPAU、VIDEOTOOLBOX、MEDIACODEC。 有的支持 Windows 平台&#xff0c;有的支持 linux 平台&#xff0c;有的支持 apple ios 平台&#xff0c;…

和鲸科技与智谱AI达成合作,共建大模型生态基座

近日&#xff0c;上海和今信息科技有限公司&#xff08;简称“和鲸科技”&#xff09;与北京智谱华章科技有限公司&#xff08;简称“智谱AI”&#xff09;签订合作协议&#xff0c;双方将携手推动国产通用大模型的广泛应用与行业渗透&#xff0c;并积极赋能行业伙伴探索领域大…

Redis核心技术与实战【学习笔记】 - 16.Redis 缓存异常:缓存和数据库不一致

概述 只要使用 Redis 缓存&#xff0c;就必须面对缓存和数据库的一致性问题。 重要的是&#xff0c;如果数据不一致&#xff0c;那么业务应用从缓存中读取的数据就不是最新数据&#xff0c;这会导致严重的问题。比如说&#xff0c;我们把电商商品的库存信息缓存在 Redis 中&am…

【Tomcat与网络3】Tomcat的整体架构

目录 1.演进1&#xff1a;将连接和处理服务分开 2演进2&#xff1a;Container的演进 3 再论Tomcat的容器结构 4 Tomcat处理请求的过程 5 请求的处理过程与Pipeline-Valve管道 在前面我们介绍了Servlet的基本原理&#xff0c;本文我们结合Tomcat来分析一下如何设计一个大型…

C语言第十七弹---指针(一)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 指针 1、内存和地址 1.1、内存 2、指针变量和地址 2.1、取地址操作符&#xff08;&&#xff09; 2.2、指针变量和解引用操作符&#xff08;*&#xff09;…

GrayLog踩坑历险记

背景 GrayLog作为ELK的替代产品&#xff0c;是新生代的日志采集框架。在一个采集节点日志的需求中&#xff0c;因为节点很多&#xff0c;产生的日志也很多&#xff0c;因此尝试了使用GrayLog进行日志的采集。下面记录一下使用GrayLog中遇到的坑和解决方案。 一、部署与启动 …

Mysql连接编译踩坑问题

复习下mysql基本命令 登录mysql mysql #没密码登录 mysql -u root -p #以用户名root 需要交互输入密码方式登录显示所有数据库 SHOW DATABASES&#xff1b; 使用某个数据库 use database_name; 查看当前数据库某一张表的表结构 DESCRIBE table_name; 解决一个mysql 用…

汽车软件开发模式的5个特点

汽车软件开发属于较为复杂的系统工程&#xff0c;经常让来自不同知识背景的工程师在观点交锋时出现分歧。在解决复杂性和对齐讨论基准时&#xff0c;可以通过勾勒出讨论对象最关键的几个特征来树立典型概念。本文旨在通过5个典型特点的抽取&#xff0c;来勾勒出汽车软件开发模式…

通过 ChatGPT 的 Function Call 查询数据库

用 Function Calling 的方式实现手机流量包智能客服的例子。 def get_sql_completion(messages, model"gpt-3.5-turbo"):response client.chat.completions.create(modelmodel,messagesmessages,temperature0,tools[{ # 摘自 OpenAI 官方示例 https://github.com/…

一张证书如何改变职业生涯?程序员必看!

随着信息产业的迅猛发展&#xff0c;对行业人才的需求也在逐年扩大。据统计&#xff0c;未来五年&#xff0c;我国对信息化人才的总需求量将高达1500万至2000万人。以软件开发为例&#xff0c;我国对软件人才的需求正以每年20%的速度递增&#xff0c;每年新增的需求接近百万。计…

第五讲:函数与类库

第五讲&#xff1a;函数与类库 第五讲&#xff1a;函数与类库函数定义实参变量的作用域返回值代码复用 类创建和使用类继承导入类 模块与库概念标准库第三方库 第五讲&#xff1a;函数与类库 函数 定义 函数就是代码块&#xff0c;只不过我们给这个代码块特地进行命名&#…

好的问卷设计标准:确保数据质量与准确性的关键要素

问卷的主要由三个部分组成&#xff1a;问卷说明、问卷主题、问卷结束。而这三个部分又包含了很多因素&#xff0c;比如问卷主题、问卷标题、问卷题目、问卷调查对象等。制作问卷不仅仅是简单的问题罗列&#xff0c;然后进行发放。不同质量的调查问卷会反馈出不一样的效果&#…

网络安全全栈培训笔记(60-服务攻防-中间件安全CVE复现WeblogicJenkinsGlassFish)

第60天 服务攻防-中间件安全&CVE复现&Weblogic&Jenkins&GlassFish 知识点: 中间件及框架列表: lIS,Apache,Nginx,Tomcat,Docker,Weblogic,JBoos,WebSphere,Jenkins, GlassFish,Jira,Struts2,Laravel,Solr,Shiro,Thinkphp,Sprng,Flask,jQuery 1、中间件-Web…

【面试深度解析】掌上先机后端面试(Java基础能力夯实)

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

01-Java工厂模式 ( Factory Pattern )

工厂模式 Factory Pattern 摘要实现范例 工厂模式&#xff08;Factory Pattern&#xff09;提供了一种创建对象的最佳方式 工厂模式在创建对象时不会对客户端暴露创建逻辑&#xff0c;并且是通过使用一个共同的接口来指向新创建的对象 工厂模式属于创建型模式 摘要 1. 意图 …

AJAX的原理(重点)

◆ XMLHttpRequest 什么是XMLHttpRequest&#xff1f; 定义&#xff1a; 关系&#xff1a;axios 内部采用 XMLHttpRequest 与服务器交互 注意&#xff1a;直白点说就是axios内部就是封装了XMLHttpRequest这个对象来实现发送异步请求的 使用 XMLHttpRequest 步骤&#xff1a…

【lesson2】定长内存池的实现

文章目录 介绍定长内存池的设计定长内存池的实现需要成员变量需要的成员函数定长内存池结构定长内存池Delete&#xff08;释放空间&#xff09;的实现定长内存池New&#xff08;申请空间&#xff09;的实现 定长内存池的实现完整版 介绍 作为程序员(C/C)我们知道申请内存使用的…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Gauge组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Gauge组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Gauge组件 数据量规图表组件&#xff0c;用于将数据展示为环形图表。 子组件 无…