九.流

news/发布时间2024/7/27 15:18:13

内容参考:

C++文件读写详解(ofstream,ifstream,fstream)_c++ 文件读写-CSDN博客

一. 概述

分类:

在程序设计中,用于输入/输出的流是必不可少的。C++中,依照用途不同,流可以被划分位三种:

  • 标准IO流:内存与标准输入、输出设备间的通信,一般是控制台。
  • 文件IO流:内存与外部文件之间的通信。
  • 字符串IO流:内存变量与字符串流的字符串数组之间的消息传递。

类关系图:

可以看出:

  • ios:所有流的基类,保存流的状态并处理错误。
  • 标准IO流:
    • istream:输入流。C+为该类创建了cin对象,并重载了>>操作符,用于输入。
    • ostream:输出流。C++为该类创建了cout对象,并重载了<<操作符,用于输出。
    • iostream:输入输出流。C++为该类创建了cerr对象,是导出程序错误消息的地方,只允许向屏幕设备写数据。
  • 文件IO流:
    • ifstream:文件输入流类。
    • ofstream:文件输出流类。
    • fstream:文件输入、输出流类。
  • 字符串IO流:串流提供了两套类,一套基于C类字符串char*编写,定义于头文件strstream;一套基于std::string编写,定义于头文件sstream。C++委员会推荐使用后者。
    • 基于std::string编写的:
      • istringstream:串输入流
      • ostringstream:串输出流
      • stringstream:串输入、输出流
    • 基于char*编写的:
      • istrstream:串输入流
      • ostrstream:串输出流
      • strstream:串输入、输出流
  • 缓冲区:包括streambuffilebufstringbuf。流与控制台、文件、字符串之间的读写并不是直接进行的,而是通过一个缓冲区,内容先经过缓冲区,然后缓冲区在一定条件下将内容再传递出去。

二. 文件流

如上文所述,文件流包括三种:

  • ifstream:文件输入流类。
  • ofstream:文件输出流类。
  • fstream:文件输入、输出流类。

这里主要记录fstream流的内容。

头文件:

#include <fstream>

1. 打开文件

成员函数。

函数原型:

void open ( const char * filename,ios_base::openmode mode = ios_base::in | ios_base::out );void open(const wchar_t *_Filename,ios_base::openmode mode= ios_base::in | ios_base::out,int prot = ios_base::_Openprot);
  • filename:文件名,也就是文件的地址。

  • mode:打开文件的方式,定义于所有流的基类ios中,有如下几种方式:

    ios::in 为输入(读)而打开文件
    ios::out 为输出(写)而打开文件
    ios::ate 初始位置:文件尾
    ios::app 所有输出附加在文件末尾
    ios::trunc 如果文件已存在则先删除该文件
    ios::binary 二进制方式

    这些方式之间可以组合使用,使用运算符进行组合,例如:

    #include <fstream>
    ofstream out;
    out.open("Hello.txt", ios::in|ios::out|ios::binary)                 //根据自己需要进行适当的选取
    
  • prot:打开文件的属性,一般很少用到,在流基类ios中定义:

    0 普通文件,打开操作
    1 只读文件
    2 隐含文件
    4 系统文件

注意:

文件相关的流在构造函数中调用了open()函数,因此可以直接使用流对象进行文件的操作。例如:

ofstream out("hello.txt", ios::out);
ifstream in("hello.txt", ios::in);
fstream io("hello.txt", ios::in|ios::out);

判断文件是否打开成功:

成员函数is_open()

#include <fstream>
fstream stream;stream.open("demo.txt");
// 判断文件是否打开成功
if (!stream.is_open()) {cout << "文件打开失败!" << endl;system("pause");exit(-1);
}

2. 关闭文件

函数:close()

注意:

  • 在使用流读取文件时,该流不能用于读取其余文件,该文件也无法被其余进程访问。在对文件的读写操作结束之后,我们必须要关闭流,从而将缓存中的数据释放出来并关闭文件。
  • 文件相关的流为了避免程序员忘记关闭流,在析构函数中调用了close()函数。

3. 文本文件的读写

3.1 写

文件流类重载了流插入运算符<<,通过流对象和<<运算符,即可写文件。

#include <fstream>
fstream stream;
stream.open("hello.txt", ios::in);
stream << "hello\n";
stream << "world!";
stream.close();

3.2 读

依次读:

和写类似,读也需要流输出运算符>>

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>int main () {char buffer[256];ifstream in("test.txt");if (! in.is_open()){ cout << "Error opening file"; exit (1); }while (!in.eof() ){in.getline (buffer,100);cout << buffer << endl;}return 0;
}

输出:

//结果 在屏幕上输出This is a line.This is another line

这里我们使用了一个新的成员函数eof(),它是从类ios中继承过来的。当到达文件末尾时,返回true

按行来读:

通过成员函数getlint(),可以一次读取一行。

#include <fstream>
fstream io;
string line;io.open("text.txt");// 从文件中读取一行数据,并将读取到的数据写入字符串变量line中
getline(io, line);

3.3 校验读写状态

文件流类中有一些成员函数用于校验流的状态:

  • bad():如果在读写过程中出错,返回 true 。例如:当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候。
  • fail():除了与bad() 同样的情况下会返回 true 以外,加上格式错误时也返回true ,例如当想要读入一个整数,而获得了一个字母的时候。
  • eof():如果读文件到达文件末尾,返回true。
  • good():这是最通用的:如果调用以上任何一个函数返回true 的话,此函数返回 false 。

3.4 流指针

在使用流对象读写文件时,至少存在一个流指针,指向文件中的内容。这些指针如下:

  • ifstream:类似istream, 有一个被称为get pointer的指针,指向下一个将被读取的元素。
  • ofstream:类似 ostream, 有一个指针 put pointer ,指向写入下一个元素的位置。
  • fstream,:类似 iostream, 同时继承了get 和 put两个指针。

获取指针:

tellg()tellp()

这两个成员函数不用传入参数,返回pos_type 类型的值(根据ANSI-C++ 标准) ,就是一个整数,代表当前get 流指针的位置 (用tellg) 或 put 流指针的位置(用tellp).

设置指针位置:

seekg()seekp()
这对函数分别用来改变流指针get 和put的位置。两个函数都被重载为两种不同的原型:

  •   seekg ( pos_type position );seekp ( pos_type position );
    

    参数:

    position:流指针改变指向后的绝对位置。要求传入的参数类型必须与函数 tellg 和tellp 的返回值类型相同。

    使用这个原型,流指针被改变为指向从文件开始计算的一个绝对位置。要求传入的参数类型与函数 tellg 和tellp 的返回值类型相同。

  •   seekg ( off_type offset, seekdir direction );seekp ( off_type offset, seekdir direction );
    

    参数:

    • offset:偏移量。

    • direction:开始计算偏移的位置:

      • ios::beg:从流开始位置计算的位移。

      • ios::cur:从流指针当前位置开始计算的唯一。

      • ios::end:从流末尾处开始计算的位移。

注意:
流指针 get 和 put 的值对文本文件(text file)和二进制文件(binary file)的计算方法都是不同的,因为文本模式的文件中某些特殊字符可能被修改。由于这个原因,建议对以文本文件模式打开的文件总是使用seekg 和 seekp的第一种原型,而且不要对tellg 或 tellp 的返回值进行修改。对二进制文件,你可以任意使用这些函数,应该不会有任何意外的行为产生。

EG:使用流指针来获取一个二进制文件的大小:

#include <iostream.h>
#include <fstream.h>const char * filename = "test.txt";int main () {long l,m;ifstream in(filename, ios::in|ios::binary);l = in.tellg();in.seekg (0, ios::end);m = in.tellg();in.close();cout << "size of " << filename;cout << " is " << (m-l) << " bytes.\n";return 0;
}//结果:
size of example.txt is 40 bytes.

4. 二进制文件的读写

在二进制文件中,依旧可以使用<<>>以及函数getline()来进行输入和输出,但这需要我们对二进制进行转化,这相当麻烦。

文件流包含两个为顺序读写数据而特殊设计的成员函数:

  •   write ( char * buffer, streamsize size );
    
    • 来源:是ostream 的一个成员函数,被ofstream所继承。由于存在继承链ostream->iostream->fstream,因此fstream也继承了该成员函数。
    • 参数:
      • buffer:要写入的数据。
      • size:要写入的字符数。
  •   read ( char * buffer, streamsize size );
    
    • 来源:是istream的一个成员函数,被ifstream 所继承。由于存在继承链istream->iostream->fstream。因此fstream也继承了该成员函数。

EG:

// reading binary file
#include <iostream>
#include <fstream.h>const char * filename = "test.txt";int main () {char * buffer;long size;ifstream in (filename, ios::in|ios::binary|ios::ate);size = in.tellg();in.seekg (0, ios::beg);buffer = new char [size];in.read (buffer, size);in.close();cout << "the complete file is in a buffer";delete[] buffer;return 0;
}
//运行结果:
The complete file is in a buffer

5. 缓存与同步

当我们使用流对文件进行操作时,流并没有直接接触到文件,而是通过一个streambuff类型的缓存(buff)和文件进行交互。这个缓存实际上是一块内存空间,它的原理是:

  1. 一个流读/写一个文件n个字符。
  2. n个字符先进入该流的缓存(buff)中。
  3. 缓存(buff)排放(flush)时,它里面的数据会被真正写入文件或读出。这一步被称之为同步(synchronization)。同步会发生的情况如下:
    • 当文件被关闭时:在文件被关闭之前,所有还没有被完全写出或读取的缓存都将被同步。
    • 当缓存buffer 满时:缓存Buffers 有一定的空间限制。当缓存满时,它会被自动同步。
    • 控制符明确指明:当遇到流中某些特定的控制符时,同步会发生。这些控制符包括:flushendl
    • 明确调用函数sync(): 调用成员函数sync() (无参数)可以引发立即同步。这个函数返回一个int 值,等于-1 表示流没有联系的缓存或操作失败。

三. 字符流

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

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

相关文章

教职云智慧职教视频课件课程下载工具,如何在电脑端下载智慧职教视频课程课件资料到本地?

一. 安装智慧职教课程下载器 1.获取学无止下载器 https://www.xuewuzhi.cn/icve_downloader 2.下载安装后,然后点击桌面快捷方式运行即可。 注意:杀毒软件可能会阻止外部exe文件运行,并将其当做成病毒,直接添加信任即可,本软件绝对没有木马病毒。 二. 使用说明 1.学无止下…

vulnhub-DC-6

DC-6 是另一个专门建造的易受攻击的实验室,旨在获得渗透测试领域的经验。这不是一个过于困难的挑战,因此对于初学者来说应该很棒。🖳 主机发现 sudo netdiscover -i eth0 -r 192.168.1.0/24Currently scanning: Finished! | Screen View: Unique Hosts …

第二十三天:MYSQL集群Cluster

一、MySQL 主从复制1、主从复制架构和原理 读写分离 复制:每个节点都有相同的数据集,向外扩展,基于二进制日志的单向复制 2、复制架构 (1)一主一从复制架构 (2)一主多从复制架构3、主从复制原理主从复制相关线程 主节点: dump Thread:为每个Slave的I/O Thread启动一个…

动态规划-DP 完整版

动态规划 学完了五大基础dp 做个简单总结dp特征动态规划问题 首要是找到做题的目的 是求最大/小值 还是其他; 其二 要确定问题的状态转移方程 这是关键; 第三 为dp数组找到边界、 最后 检查是否需要结合其他相关知识 如树 dfs等; 别忘了检查多测输入 数组变量置零等易错点。…

DVWA-Insecure CAPTCHA(不安全的验证码)

Insecure CAPTCHA 意思是不安全的验证码,指验证在验证过程中,存在逻辑漏洞,导致可以绕过验证。CAPTCHA全称为:Completely Automated Public Turing Test to Tell Computers and Humans Apart (全自动区分计算机和人类的图灵测试)。 DVWA-Insecure CAPTCHA级别:--low--medi…

VSCOde+Nodejs+Typescript前端开发环境

1.安装Node.js 下载地址:https://nodejs.org/en lts版本: 长久稳定版本 安装:默认安装就可以了 验证:node2.VSCode 下载地址:https://code.visualstudio.com/Download 安装:默认安装 语言切换: 安装中文插件,重启3.支持TypeScript TypeScript是JavaScript的超集,强制进…