C++文件操作(2)
文件操作(2)
- 1.二进制模式读取文本文件
- 2.使用二进制读写其他类型内容
- 3.fstream类
- 4.文件的随机存取
- 文件指针的获取
- 文件指针的移动
1.二进制模式读取文本文件
用二进制方式打开文本存储的文件时,也可以读取其中的内容,因为文本文件本质上是存储字符类型数据。这种方式读取文件内容我们需要用到string类型的方法:
int main()
{ifstream mytest("test.txt",ios::in|ios::binary); // ios::in是默认参数,可以不写if(mytest.is_open()){cout<<"打开文件失败"<<endl;return 0;}// 二进制文件读取后需要用正确的接收格式接收// string out((istreambuf_iterator<char>(mytest)), (istreambuf_iterator<char>())) // 直接使用string的构造函数对out进行赋值string out;out.assign((istreambuf_iterator<char>(mytest)), (istreambuf_iterator<char>())); // 使用assign函数赋值cout<<out;// 关闭文件mytest.close();
}
istreambuf_iterator会迭代访问文件内容,读取完成后out会存贮整个文件的内容,不需要一行一行读取:
2.使用二进制读写其他类型内容
有时候我们也需要借由二进制模式处理一些非文本形式的简单数据,比如数字数组。这样的类型处理方法和上一节用结构体类型读写二进制文件很相似:
int main()
{ofstream mytest("nums.txt",ios::app|ios::binary); // 读取二进制文件if(mytest.is_open()){// 二进制文件读取后需要用正确的接收格式接收int numbers[]={10,15,20,30,55,67};mytest.write(reinterpret_cast<const char*>(numbers),sizeof(numbers));}else{cout<<"打开文件失败"<<endl;return 0;}// 关闭文件mytest.close();
}
这里我们将一个整形数组以二进制形式写成了二进制文件,这里的reinterpret_cast<const char*>(numbers)是C++指针类型的强制转换,等同于(const char*)numbers。
当我们想要读取时,也用类似的办法处理。值得注意的是,如果我们知道数组的具体大小,读取内容的任务又会简单许多:
int main()
{ifstream mytest("nums.txt",ios::in|ios::binary);if(mytest.is_open()){int numbers[6];mytest.read(reinterpret_cast<char*>(numbers), sizeof(numbers));// 查看内容是否正确存储到整形数组里for(int i=0;i<=5;i++){cout<<numbers[i]<<" ";}}else{cout<<"打开文件失败"<<endl;return 0;}// 关闭文件mytest.close();
}
// 输出为:10 15 20 30 55 67
如果换成长度已知的结构体数组,也可以这样处理。
如果我们不知道数组的具体长度,也可以一个一个读出文件的存储内容:
int main()
{ifstream mytest("nums.txt",ios::in|ios::binary); // 读取二进制文件if(mytest.is_open()){int number;while(mytest.read((char*)&number,sizeof(int))){cout<<number<<" ";}}else{cout<<"打开文件失败"<<endl;return 0;}// 关闭文件mytest.close();
}
输出结果同上例一样。
3.fstream类
在C语言中,文件操作只有文件指针,没有输入输出流的区别,C++是在C基础上将输入和输出分别封装成类,ifstream类用于读文件,ofstream用于写入文件。但是C++也保留了同时可以完成读写的类:fstream。它的使用方法与ifstream和ofstream完全相似,如果我们想写如文件:
int main()
{fstream mytest("test.txt"); if(mytest.is_open()){mytest<<"这是另一个测试\n";}else{cout<<"打开文件失败"<<endl;return 0;}// 关闭文件mytest.close();
}
如果我们想读取文件:
int main()
{fstream mytest("test.txt"); if(mytest.is_open()){string out;while(mytest>>out){cout<<out<<endl;}}else{cout<<"打开文件失败"<<endl;return 0;}// 关闭文件mytest.close();
}
// 输出为:这是一个测试
// 我们尝试连续输入内容
// 继续测试这是一个测试
// 我们尝试连续输入内容
// 这是一个测试
// 我们尝试连续输入内容
// 这是另一个测试
我们以打开文本文件为例,展示了fstream类用法,操作二进制文件的方法也可以直接照搬ifstream和ofstream类。但是fstream仍有一些细节需要我们注意,fstream类的默认写参数是ios::out和ios::in,至于具体执行那种操作会根据后面的代码进行确定。写入文件时默认参数ios::out参数在没有文件时会创建文件,但再有文件时是默认在文件最后写内容,类似于ios::app。fstream打开文件时还有一些参数可供使用:
ios::ate 以定位到文件末尾的方式打开文件
ios::in|ios::out 以读写方式打开文件
ios::out|ios::truct 如果文件存在,则截断文件重新写入内容,类似于ofstream类的out模式。
通常情况下,规范的编程通常在需要写文件的时候使用ofstream,需要读的时候用ifstream,即需要读又需要写的时候再使用fstream类。在Linux平台下,读和写有严格的权限控制,为了方便管理,我们调用的权限应当尽量少。举个例子,如果我们只需要读取文件,那么即使我们有读写的权限,也应当以只读方式打开文件。
4.文件的随机存取
之前我们介绍了文件的写入都是在文件的末尾或删除文件内容后再写入内容,而读文件都是从文件的开头进行的。这是因为读写文件都是从文件位置指针1处开始的,我们之前的操作文件的方式,文件指针都会在文件的最开始或最末尾。实现文件的随机存取,关键就在于调整文件指针所在位置。
文件指针的获取
获取文件指针位置的方法,输入流ofstream类为成员函数是 tellp();输出流ifstream类为成员函数是 tellg();fstream类两个成员函数都有且效果完全相同。以写文件为例:
int main()
{ofstream mytest("test1.txt",ios::app); if(mytest.is_open()){cout<<mytest.tellp()<<endl;mytest<<"以写入文本为例\n";cout<<mytest.tellp()<<endl;}else{cout<<"打开文件失败"<<endl;return 0;}// 关闭文件mytest.close();
}
// 输出为:0
// 22
读取文件同时获取文件指针的方法与写入相同:
// Student结构体上节内容中有所定义
int main()
{ifstream mytest("test.doc",ios::app|ios::binary); if(mytest.is_open()){cout<<mytest.tellg()<<endl;Student child;while(mytest.read((char*)&child,sizeof(child))){cout<<child.name<<" "<<child.age<<" "<<child.sex<<endl;cout<<"mytest.tellg()="<<mytest.tellg()<<endl;}}else{cout<<"打开文件失败"<<endl;return 0;}// 关闭文件mytest.close();
}
// 输出为:0
// ZhangSan 15 m
// mytest.tellg()=40
// LiSi 20 m
// mytest.tellg()=80
可以看到,在二进制文件中获取文件指针位置的方法与文本文件相同。此外,给大家说个冷知识,使用ios::app打开文件除了可以在文件末尾追加内容,也可以用于读取文件信息,文件指针位置会根据任务自动进行调整。不过为了规范编程尽量不要这样乱用。
fstream类在这里就不做展示了,用法完全相同大家可以自行尝试。
PS:文件只有一个位置指针,并非同时拥有读指针和写指针。
文件指针的移动
文件的读和写都是在当前文件指针的位置往后进行的,也就是说如果我们能够移动文件的位置指针就可以做到调整读写数据的位置。C++中为我们提供了这样的方法,ifstream类使用seekg()成员函数移动文件指针,ofstream类使用seekp()成员函数移动文件指针,fstream类依旧是两者都可用,效果相同。
seekp和seekg有两个常用的重载,第一种为:
seekg(ios::beg) 将文件指针移动到0位置
seekg(ios::end) 将文件指针移动到末尾
seekg(128) 将文件指针移动到指定位置,这里指定文件指针移动到128位置
注:将seekg换成seekp效果完全类似
我们看个例子:
int main()
{ifstream mytest("test.txt",ios::in); if(mytest.is_open()){mytest.seekg(29);cout<<mytest.tellg()<<endl;string out;while(mytest>>out){cout<<out<<" "<<"当前位置为:"<<mytest.tellg()<<endl;}}else{cout<<"打开文件失败"<<endl;return 0;}mytest.close();
}
输出结果为:
另外需要注意,由于一个中文占3个字节,因此我需要注意文件指针所在位置不能在某个中文字的内部。假如使用mytest.seekg(28),输出内容就会出现异常。
另一种常用seek方法的重载有两个参数:
seekg(10,ios::beg) 文件指针从0位置开始向后移动10字节
seekg(-3,ios::end) 文件指针从末尾开始向前移动3字节
seekg(5,ios::cur) 文件指针从当前位置开始向后移动5字节
注:将seekg换成seekp效果完全类似
还是看个例子:
// student类与test.doc文化部在上节中已经定义和创建
int main()
{fstream mytest("test.doc",ios::in | ios::out | ios::binary ); // 使用读写模式打开二进制文件test.docif(mytest.is_open()){cout<<mytest.tellg()<<endl;Student child;while(mytest.read((char*)&child,sizeof(child))){cout<<child.name<<" "<<child.age<<" "<<child.sex<<endl;cout<<"mytest.tellg()="<<mytest.tellg()<<endl;}// 清除文件状态流的标志mytest.clear();cout<<"\n以上内容作为对比\n"<<endl;mytest.seekg(-40,ios::cur);child=Student{"WangWu",22,'w'};mytest.write((const char*)&child,sizeof(Student));mytest.seekg(ios::beg);while(mytest.read((char*)&child,sizeof(child))){cout<<child.name<<" "<<child.age<<" "<<child.sex<<endl;cout<<"mytest.tellg()="<<mytest.tellg()<<endl;}mytest.close();}else{cout<<"打开文件失败"<<endl;return 0;}
}
在这段代码中,大家可能会不理解mytest.clear()的用意,在我们使用while循环读取文件的全部内容后,failbite会被设置为true2,这标志会让计算机认为文件遇到错误,后面就无法正常对文件进行操作了。使用clear函数可以清除这些标志,后面才能继续操作文件。
输出是这样的:
可以看到我们虽然移动了文件指针,在再定位置添加了内容,但是原有的内容却是被覆盖掉了。如果我们想要保留原来的内容,需要将插入位置后面的内容向后移动若干单位,实现方法类似于在数组中插入一个数。
本节我们继续学习了C++操作文件的方法,其中,改变文件指针的位置是我们学习的重点。在实际应用中,我们经常会遇到需要从指定位置读取和写入内容的任务,希望大家能够掌握本节内容。
在C++中,文件位置指针的指向就是文件中进行读取或写入操作时的初始位置。 ↩︎
除了我们用过的方法(如is_open())外,文件流还有很多比较实用的方法,如使用eof()方法判断是否到达文件末尾,使用good函数判断文件写入是否成功,使用get函数按字符提取文本内容等,在下一节还会具体介绍。 ↩︎
相关文章:

C++文件操作(2)
文件操作(2) 1.二进制模式读取文本文件2.使用二进制读写其他类型内容3.fstream类4.文件的随机存取文件指针的获取文件指针的移动 1.二进制模式读取文本文件 用二进制方式打开文本存储的文件时,也可以读取其中的内容,因为文本文件…...

Bootstrap5 图片轮播
Bootstrap5 轮播样式表使用的是CDN资源 <title>亚丁号</title><!-- 自定义样式表 --><link href"static/front/css/front.css" rel"stylesheet" /><!-- 新 Bootstrap5 核心 CSS 文件 --><link rel"stylesheet"…...

WINDOWS搭建NFS服务器
下载并安装 Networking Software for Windows 启动配置 找到安装目录(如C:\Program Files\nfsd),双击nfsctl.exe,菜单Edit->Preferences 启动后: 配置Export Exports->Edit exports file 其他的几句我都删除…...

LeetCode、216. 组合总和 III【中等,组合型枚举】
文章目录 前言LeetCode、216. 组合总和 III【中等,组合型枚举】题目类型与分类思路 资料获取 前言 博主介绍:✌目前全网粉丝2W,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖…...

支持534种语言,开源大语言模型MaLA-500
无论是开源的LLaMA 2还是闭源的GPT系列模型,功能虽然很强大,但对语言的支持和扩展比较差,例如,二者都是以英语为主的大模型。 为了提升大模型语言的多元化,慕尼黑大学、赫尔辛基大学等研究人员联合开源了,…...
面试 JavaScript 框架八股文十问十答第一期
面试 JavaScript 框架八股文十问十答第一期 作者:程序员小白条,个人博客 相信看了本文后,对你的面试是有一定帮助的!关注专栏后就能收到持续更新! ⭐点赞⭐收藏⭐不迷路!⭐ 1)JavaScript有哪些…...

【发票识别】新增针对图片发票的识别(升级中)
说明 为了完善发票识别的功能,目前发票识别支持发票图片格式的识别,增加可用性。 体验 体验地址:https://invoice.behappyto.cn/invoice-service/ 体验地址上面有示例的发票,可以下载上传识别或者复制url地址进行识别。 技术栈…...

面试数据结构与算法总结分类+leetcode目录【基础版】
🧡🧡🧡算法题目总结: 这里为大家总结数据结构与算法的题库目录,如果已经解释过的题目会标注链接更新,方便查看。 数据结构概览 Array & String 大家对这两类肯定比较清楚的,同时这也是面试…...

音频二维码怎么制作出来的?支持多种格式音频生码的方法
怎么把一个音频的文件做成二维码图片呢?在日常工作和生活中,有很多的场景会需要使用音频类型的文件来展示内容,比如常见的英语听力、课程、听书等类型的内容,现在都可以用二维码展示。而且现在生成音频二维码的方法也很简单&#…...

ReactNative实现一个圆环进度条
我们直接看效果,如下图 我们在直接上代码 /*** 圆形进度条*/ import React, {useState, useEffect} from react; import Svg, {Circle,G,LinearGradient,Stop,Defs,Text, } from react-native-svg; import {View, StyleSheet} from react-native;// 渐变色 const C…...

【JS逆向学习】今日头条
逆向目标 目标网页:https://www.toutiao.com/?wid1707099375036目标接口:https://www.toutiao.com/api/pc/list/feed目标参数:_signature 逆向过程 老规矩先观察网络请求,过滤XHR请求观察加密参数,发现Payload的_s…...

Tailwind CSS
目录 引入原因: css增长,样式错乱 调试 规范:在class上原子化css 特点:把class当行内style动态属性用 优点 不用命名样式 不用想并不重要的CSS变量名 缺少命名逻辑 不用撰写维护和模板【对应的独立css块】 不用不停滚…...

Go语言每日一练——链表篇(五)
传送门 牛客面试笔试必刷101题 ----------------合并k个已排序的链表 题目以及解析 题目 解题代码及解析 解析 这一道题与昨天的合并链表题目类似,但是由于有K个且时间复杂度要求控制在O(nlogn),这里主要有两种解法:一种是依旧使用归并来…...

5-4、S加减单片机程序【51单片机+L298N步进电机系列教程】
↑↑↑点击上方【目录】,查看本系列全部文章 摘要:本节介绍实现步进电机S曲线运动的代码 一、目标功能 实现步进电机转动总角度720,其中加减速各90 加速段:加速类型:S曲线 加速角度:角度为90 起步速度…...

【安卓跨程序共享数据,探究ContentProvider】
ContentProvider主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问数据的安全性。 目前,使用ContentProvider是Android实现跨程序共享数据的标准方…...

abap - 发送邮件,邮件正文带表格和excel附件
发送内容 的数据获取: 正文部分使用cl_document_bcs>create_document静态方法实现 传入参数为html内表结构 CLEAR lo_document .lo_document cl_document_bcs>create_document(i_type HTMi_text lt_htmli_length conlengthsi_subject lv_subje…...
Ubuntu编译和测试ITK4.13.1
安装不麻烦,环境配置挺麻烦,主要是gcc、cmake和ccmake的版本不匹配问题。 环境: gcc -- 7.5.0 cmake -- 3.15.2 ccmake -- 3.15.2 参考以下两篇博客安装: 1、 ITK的安装与测试(Ubuntu系统)_ubuntu20…...
【C语言】简易计算器转移表(函数指针简化)
什么是转移表? 转移表是一种根据输入条件进行分支选择的技术。它通常用于根据不同的条件执行不同的操作。在 C 语言中,我们可以使用 switch 语句来创建转移表,根据表达式的值选择不同的分支执行。 计算器转移表的普通实现 #include<stdi…...

JavaBase持续更新
仅作笔记📒, 尚不完善, 持续更新中… 一、Java概述 1.1 Java语言发展史 语言: 人与人交流沟通的表达方式 计算机语言: 人与计算机之间进行信息交流沟通的一种特殊语言 Java语言是美国Sun公司(Stanford University Network)在1995年推出的…...

AI专题:海外科技巨头指引,AI主线逻辑依旧坚挺
今天分享的是AI 系列深度研究报告:《AI专题:海外科技巨头指引,AI主线逻辑依旧坚挺》。 (报告出品方:华西证券) 报告共计:54页 本周热点:海外科技巨头指引,AI主线逻辑依旧坚挺 硬件…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...