C++文件操作和文件流

2023-11-09

1文件的概念

根据文件中数据的组织方式,可以将文件分为文本文件二进制文件

  • 文本文件:又称字符文件或ASCII文件,它的每一个字节放一个ASCII代码,代表一个字符。
  • 二进制文件:又称内部格式文件或字节文件,是把内存中的数据按其在内存中的存储形式原样输出到磁盘中存放。

比如:数字 64 在内存中表示为 0100 0000,若将其保存为 文本文件,则要分别存放十位 6 和个位 4 的 ASCII 码,为 0011 0110 0011 0100,占用两个字节;若将其保存为二进制文件,则按内存中形式直接输出,为 0100 0000,占用一个字节。

文本文件中数据与字符一一对应,一个字节代表一个字符,可以直接在屏幕上显示或打印出来,这种方式使用方便,比较直观,便于阅读,但一般占用存储空间较大,而且输出时要将二进制转化为 ASCII 码比较花费时间。

二进制文件,输出时不需要进行转化,直接将内存中的形式输出到文件中,占用存储空间较小,但一个字节并不对应一个文件,不能直观显示文件中的内容。

2 文件流的分类

文件流是以外存文件未输入输出对象的数据流。输出文件流是从内存流向外存文件的数据,输入文件流是从外存文件流向内存的数据。每一个文件流都有一个内存缓冲区与之对应。

C++有三个用于文件操作的文件类:

ofstream //文件的写操作(输出),主要是从内存写入存储设备(如磁盘),继承了istream类
ifstream //文件的读操作(输入),主要是从存储设备中读取数据到内存,继承了ostream类
fstream //文件的读写操作,对打开的文件可进行读写操作,继承了iostream类

操作的过程:要以磁盘文件(外存文件)为对象进行输入输出,必须定义一个文件流类的对象,通过文件流对象将数据从内存输出到磁盘文件,或者将磁盘文件输入到内存。

定义文件流对象后,我们还需要将文件流对象和指定的磁盘文件建立关联,以便使文件流流向指定的磁盘文件,并确定文件的工作方式(是输入还是输出,二进制还是文本)。我们可以在定义流对象的时候指定参数来调用构造函数,或者通过成员函数open()来进行文件流对象和指定文件的关联(后面会讲)。

C++中输入输出流关系如下:
在这里插入图片描述

以上,箭头表示继承关系。

istream,ostream,iostream三者为例,看一下具体的继承关系,如下:

template<typename _CharT, typename _Traits>
    class basic_istream : virtual public basic_ios<_CharT, _Traits>;
template<typename _CharT, typename _Traits>
    class basic_ostream : virtual public basic_ios<_CharT, _Traits>;
template<typename _CharT, typename _Traits>
    class basic_iostream
    : public basic_istream<_CharT, _Traits>,
      public basic_ostream<_CharT, _Traits>;

   /// Base class for @c char streams.
   typedef basic_ios<char>         ios; //基础类
 
   /// Base class for @c char buffers.
   typedef basic_streambuf<char>     streambuf;
 
   /// Base class for @c char input streams.
   typedef basic_istream<char>         istream;
 
  /// Base class for @c char output streams.
  typedef basic_ostream<char>         ostream;

  /// Base class for @c char mixed input and output streams.
  typedef basic_iostream<char>         iostream;

  /// Class for @c char memory buffers.
  typedef basic_stringbuf<char>     stringbuf;

  /// Class for @c char input memory streams.
  typedef basic_istringstream<char>     istringstream;

  /// Class for @c char output memory streams.           
  typedef  basic_ostringstream<char>     ostringstream;

  /// Class for @c char mixed input and output memory streams.
  typedef basic_stringstream<char>     stringstream;

  /// Class for @c char file buffers.
  typedef basic_filebuf<char>         filebuf;

 /// Class for @c char input file streams.
  typedef basic_ifstream<char>         ifstream;

  /// Class for @c char output file streams.
  typedef basic_ofstream<char>         ofstream;

  /// Class for @c char mixed input and output file streams.
  typedef basic_fstream<char>         fstream;

可以看到basic_istreambasic_ostream都是虚继承于basic_iosbasic_iostream是继承于basic_istreambasic_ostream,注意这里继承于basic_ios的时候之所以要用虚拟继承,是为了防止多重继承时,多个父类共用基类产生二义性。

2 打开文件

打开文件操作主要是把我们的文件流类对象和一个文件相关联起来,这样这个被打开的文件可以用类对象表示,之后我们对文件流类对象所做的输入和输出操作其实就是对这个文件所做的操作。

2.1 通过类对象调用open函数打开一个文件

在每个文件流的类中都定义了一个打开文件的成员函数open,函数原型如下

void open(const char* filename,ios_base::openmode mode);
//参数的含义:
   filename:  要打开的文件名
  mode:    要打开文件的方式

其中mode定义在所有IO的基类中:即ios类,它包括如下几种方式:

//文件的输入和输出是从内存的角度看的:数据载入内存叫输入,数据从内存到其他地方叫输出。
os::app     //追加模式,即所有写入都追加到文件末尾
ios::ate     //文件打开后定位到文件尾
ios::binary   //以二进制方式打开文件,缺省的方式是文本方式
ios::in    //文件以输入方式打开(文件数据输入到内存)(ifstream对象默认方式就是这个)
ios::out    //文件以输出方式打开(内存数据输出到文件)(ofstream对象默认的打开方式)
ios::nocreate //不建立文件,所以文件不存在时打开失败
ios::noreplace//不覆盖文件,所以打开文件时如果文件存在失败
ios::trunc   //如果文件存在,把文件长度设为0

mode参数可以组合起来使用,但是两个参数之间必须要用操作符|隔开,如下

ofstream out;  //声明一个ofstream对象out
out.open("text.txt",ios::out|ios::app);  //往text.txt文件中输入内容,输入方式在文件的末尾追加内容,且不清空原有的内容

或者

//这个声明方式是调用了ofstream有参构造函数,该构造函数会自动调用open函数。
ofstream out("text.txt",ios::out|ios::app)

2.2 通过类对象构造函数打开文件

ofstream, ifstreamfstream的对象所进行的第一个操作通常都是打开文件,这些类都有一个构造函数可以直接调用open 函数,并拥有同样的参数。这样,我们就可以通过以下方式进行与上面同样的定义对象和打开文件的操作:

ofstream file ("example.bin", ios::out | ios::app | ios::binary);

//例如:以二进制输入方式打开文件c:\config.sys 
fstream file1;
file1.open("c:\\config.sys",ios::binary|ios::in,0);

//如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:
file1.open("c:\\config.sys");<=>file1.open("c:\\config.sys",ios::in|ios::out,0);

//另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:
fstream file1("c:\\config.sys");

3 关闭文件

当我们完成对文件的操作后,需要调用成员函数close来关闭我们的文件流,close函数的作用其实就是清空该类对象在缓存中的内容并且关闭该对象和文件的关联关系,那个该对象可以和其他文件进行关联。

ofstream file;  //声明一个ofstream对象file
file.open("text.txt",ios::out|ios::app);  
file.close();  //关闭"text.txt"文件

为了防止一个类对象被销毁后,还和某个文件保留关联关系,所以文件流类的析构函数都会自动调用close函数。

4 读写文件

对文件读写操作要分两种:文本文件的读写、二进制文件的读写

4.1 文本文件的读写

文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。

插入器(<<) 向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<“Write
Stdout”<<‘n’;就表示把字符串"Write Stdout"和换行字符(‘n’)输出到标准输出流。

析取器(>>)
从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据

比如读取写入txt文件,如下

   #include "iostream"
   #include<fstream>
   void main()
   {
       std::fstream f("d:\\test.txt", ios::out);//定义了一个对象f,只写,"d:\\test.txt"文件不存在则创建,存在则清空原内容
       f << 1234 << ' ' << 3.14 << 'A' << "How are you"; //写入数据
       f.close();//关闭文件以使其重新变为可访问,函数一旦调用,原先的流对象就可以被用来打开其它的文件
       f.open("d:\\try.txt", ios::in);//打开文件,只读
       int i;
       double d;
       char c;
       char s[20];
       f >> i >> d >> c;               //读取数据
       f.getline(s, 20);
       std::cout << i << std::endl;    //显示各数据
       std::cout << d << std::endl;   //endl是一种格式,表示输出一个换行符,并刷新此流
       std::cout << c << std::endl;
       std::cout << s << std::endl;
       f.close();
   }

还有一些其他的格式如下

操纵符 功能
dec 格式化为十进制数值数据
endl 输出一个换行符并刷新此流
ends 输出一个空字符
hex 格式化为十六进制数值数据
oct 格式化为八进制数值数据
setpxecision(int p) 设置浮点数的精度位数

也可以利用文件流对象的成员函数 get, put 等,其用法如下:
put()
put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'

get()
get()函数比较灵活,有3种常用的重载形式:

一种就是和put()对应的形式:ifstream &get(char &ch);
功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。

另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。

还一种形式的原型是:
ifstream &get(char *buf,int num,char delim='n');
这种形式把字符读入由buf指向的数组,直到读入了num个字符或遇到了由 delim指定的字符,如果没使用 delim这个参数,将使用缺省值换行符'n'。例如:
file2.get(str1,127,'A');//从文件中读取字符到字符串str1,当遇到字符’A’或读取了127个字符时终止。

4.2 二进制文件的读写

二进制文件的操作需要在打开文件的时候指定打开方式为ios::binary,并且还可以指定为既能输入又能输出的文件,我们通过成员函数 readwrite来读写二进制文件。

//这里 buffer 是一块内存的地址,用来存储或读出数据。参数size 是一个整数值,表示要从缓存(buffer)中读出或写入的字符数。
istream& read ( char * buffer, streamsize size);
ostream& write (char * buffer, streamsize size);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++文件操作和文件流 的相关文章

  • 访问私人成员[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 通过将类的私有成员转换为 void 指针 然后转换为结构来访问类的私有成员是否合适 我认为我无权修改包含我需要访问的数据成员的类 如果不道德 我
  • 将数组向左或向右旋转一定数量的位置,复杂度为 o(n)

    我想编写一个程序 根据用户的输入 正 gt 负 include
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • C 预处理器库

    我的任务是开发源分析工具C程序 并且我需要在分析本身之前预处理代码 我想知道什么是最好的图书馆 我需要一些重量轻 便于携带的东西 与其推出自己的 为什么不使用cpp这是的一部分gcc suite http gcc gnu org onlin
  • WPF TabControl,用C#代码更改TabItem的背景颜色

    嗨 我认为这是一个初学者的问题 我搜索了所有相关问题 但所有这些都由 xaml 回答 但是 我需要的是后台代码 我有一个 TabControl 我需要设置其项目的背景颜色 我需要在选择 取消选择和悬停时为项目设置不同的颜色 非常感谢你的帮助
  • 如何将图像路径保存到Live Tile的WP8本地文件夹

    我正在更新我的 Windows Phone 应用程序以使用新的 WP8 文件存储 API 本地文件夹 而不是 WP7 API 隔离存储文件 旧的工作方法 这是我如何成功地将图像保存到 共享 ShellContent文件夹使用隔离存储文件方法
  • 将自定义元数据添加到 jpeg 文件

    我正在开发一个图像处理项目 C 我需要在处理完成后将自定义元数据写入 jpeg 文件 我怎样才能做到这一点 有没有可用的图书馆可以做到这一点 如果您正在谈论 EXIF 元数据 您可能需要查看exiv2 http www exiv2 org
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • 如何衡量两个字符串之间的相似度? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给定两个字符串text1 and text2 public SOMEUSABLERETURNTYPE Compare string t
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • 如何让Gtk+窗口背景透明?

    我想让 Gtk 窗口的背景透明 以便只有窗口中的小部件可见 我找到了一些教程 http mikehearn wordpress com 2006 03 26 gtk windows with alpha channels https web
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • Validation.ErrorTemplate 的 Wpf 动态资源查找

    在我的 App xaml 中 我定义了一个资源Validation ErrorTemplate 这取决于动态BorderBrush资源 我打算定义独特的BorderBrush在我拥有的每个窗口以及窗口内的不同块内
  • mysql-connector-c++ - “get_driver_instance”不是“sql::mysql”的成员

    我是 C 的初学者 我认为学习的唯一方法就是接触一些代码 我正在尝试构建一个连接到 mysql 数据库的程序 我在 Linux 上使用 g 没有想法 我运行 make 这是我的错误 hello cpp 38 error get driver
  • C 中的异或运算符

    在进行按位操作时 我在确定何时使用 XOR 运算符时遇到一些困难 按位与和或非常简单 当您想要屏蔽位时 请使用按位 AND 常见用例是 IP 寻址和子网掩码 当您想要打开位时 请使用包含或 然而 XOR 总是让我明白 我觉得如果在面试中被问
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob
  • 恢复上传文件控制

    我确实阅读了以下帖子 C 暂停 恢复上传 https stackoverflow com questions 1048330 pause resume upload in c 使用 HTTP 恢复上传 https stackoverflow

随机推荐

  • ui(new Ui::MainWindow)

    用最新的QtCreator选择GUI的应用会产生含有如下文件的工程 下面就简单分析下各部分的功能 pro文件是供qmake使用的文件 不是本文的重点 不过其实也很简单的 在此不多赘述 所以呢 还是从main开始 include
  • Java基础-学习笔记(一)

    1 IT业务的发展变化 1 大型机 一代 IBM 2 PC Mac 二代 微软 苹果 3 互联网 三代 Google Baidu 4 移动互联网 谷歌 微软 苹果 所谓 移动互联网 移动通信 互联网 马云所属 IT到DT的变化 注 推荐本书
  • MATLAB的曲线拟合

    原文地址 MATLAB的曲线拟合 作者 睿吉jerry MATLAB软件提供了基本的曲线拟合函数的命令 曲线拟合就是计算出两组数据之间的一种函数关系 由此可描绘其变化曲线及估计非采集数据对应的变量信息 1 线性拟合函数 regress 调用
  • 智能合约简介

    链客 专为开发者而生 有问必答 此文章来自区块链技术社区 未经允许拒绝转载 当人们在讨论智能合约的时候他们到底在说什么 在区块链和加密货币的语境中 智能合约的定义是 在分布式存储平台 例如区块链 上存储并复制的 在计算机网络 通常是运行区块
  • 【qiankun】子应用的路由信息传给主应用,主应用使用this.$router.push跳转子应用页面

    前提 已经安装qiankun 并且子应用已经接入主应用 场景 主应用是vue2 子应用是vue3 子应用的路由文件router index ts 在这段后面加下列代码 const router createRouter history cr
  • VMware Workstation 无法连接到虚拟机。请确保您有权运行该程序、访问该程序使用的所有目录以及访问所有临时文件目录的解决方法

    VMware Workstation 无法连接到虚拟机 请确保您有权运行该程序 访问该程序使用的所有目录以及访问所有临时文件目录 这个问题刚刚用虚拟机的人可能会经常遇到 解决方法就是 在开始中搜索服务 点击服务正在本电脑运行 注意 这里演示
  • CloudCompare 二次开发(5)——非插件中的PCL环境配置(均匀采样为例)

    目录 一 概述 二 CMakeLists txt 三 源码编译 四 代码示例 五 结果展示 本文由CSDN点云侠原创 原文链接 爬虫网站自重 一 概述 在进行CloudCompare二次开发的时候 可以直接在CloudCompare的核心功
  • 推动政府数字化转型进入新阶段

    推动政府数字化转型进入新阶段 公司近两年比较关注数字化转型和金融科技 打算今年重点了解一下 在网上看到了一个文章 感觉还不错 转载到这里 本文转自人民政协网上的 推动政府数字化转型进入新阶段 1 国家政策 国务院近日发布的 十四五 数字经济
  • 智慧城市智慧零售受益于5G和AI双核驱动

    支付宝推出了刷脸支付 我们只需要对准摄像头让它把我们脸部的特征完全识别出来 然后就可以进行支付了 那么这种人脸支付会用在很多地方 很简单 我们去超市购物的时候 以往你要么用卡要么给现金 或者你掏出手机来支付 但是怎么也得输入密码或者按指纹
  • MySQL自增主键详解

    一 自增值保存在哪儿 不同的引擎对于自增值的保存策略不同 1 MyISAM引擎的自增值保存在数据文件中 2 InnoDB引擎的自增值 在MySQL5 7及之前的版本 自增值保存在内存里 并没有持久化 每次重启后 第一次打开表的时候 都会去找
  • chrome浏览器:您的连接不是私密连接,burp抓包

    问题 您的连接不是私密连接 处理 简简单单 跟着我来没错 不要浪费时间再找了 插件设置 SwitchyOmega 开启代理访问http burp CA下载证书 chrome flags Allow invalid certificates
  • 第3章 数据库结构设计

    3 1数据库概念设计 数据库概念设计主要解决数据需求 即如何准确地理解数据需求 真实地把应用领域中要处理的数据组织 定义描述清楚 以支持数据库设计后续阶段的工作 3 1 1概念设计的任务 数据库概念设计阶段的目标是 1 定义和描述应用领域涉
  • 2024王道数据结构P17No11

    一个长度为L L gt 1 的升序序列S 处在第L 2位置 向下取整 的数称为S的中位数 例如 序列S1 11 13 15 17 19 则中位数为15 两个序列的中位数是含他们所有元素的升序序列的中位数 例如 S2 2 4 6 8 20 则
  • 【毕业设计】深度学习身份证识别系统 - 机器视觉 python

    文章目录 0 前言 1 实现方法 1 1 原理 1 1 1 字符定位 1 1 2 字符识别 1 1 3 深度学习算法介绍 1 1 4 模型选择 2 算法流程 3 部分关键代码 4 效果展示 5 最后 0 前言 Hi 大家好 这里是丹成学长的
  • 学习总结7.1 Linux Rsh服务器

    在线安装是指不需要用户亲自下对应软件的包 但是需要对应系统能够访问互联网 不同的Linux系统使用不同的工具进行在线安装软件 常见的在线安装软件的工具如下所示 Ubuntu Debian系统使用apt get进行在线安装软件 Redhat
  • 动态粒子爱心,表白神器源码

    效果 https www douyin com user self modal id 7187722820967763237 源码 from tkinter import from matplotlib import pyplot as p
  • FCN的代码解读

    目录 模型初始化 VGG初始化 FCN初始化 图片的预处理 图片处理 图片编码 计算相关参数 模型训练 一个小问题 完整代码 参考 最近浅研究了一下关于图像领域的图像分割的相关知识 发现水还是挺深的 因为FCN差不多也是领域的开山鼻祖 所以
  • Android无线网络调试手机

    adb tcpip 5555 adb下载地址 http download clockworkmod com test UniversalAdbDriverSetup msi 3 在设备中下载超级终端 是andriod软件 设置端口 su s
  • JVM笔记-黑马-1

    文章目录 视频资源地址 笔记资源地址 我的笔记 1 什么是JVM 2 学习jvm的作用 3 常见的jvm 4 学习路线 5 内存结构 程序计数器 作用 6 内存结构 程序计数器 特点 7 内存结构 虚拟机栈 8 内存结构 虚拟机栈的演示 9
  • C++文件操作和文件流

    C 文件操作和文件流 1文件的概念 2 文件流的分类 2 打开文件 2 1 通过类对象调用 open 函数打开一个文件 2 2 通过类对象构造函数打开文件 3 关闭文件 4 读写文件 4 1 文本文件的读写 4 2 二进制文件的读写 1文件