• C++标准库之:IO库


    C++标准库之-IO库


    C++语言不直接处理输入输出,而是通过一族定义在标准库中的类型来处理IO。
    这些类型支持从设备读取数据、向设备写入数据的IO操作,设备可以是文件、控制台窗口等。
    还有一些类型允许内存IO,即,从string读取数据,向string写入数据。

    1. IO类


    1.1 头文件和IO库类型:

    • 头文件
      • istream,wistream从流读取数据
      • ostream,wostream向流写入数据
      • iostream,wiostream读写流
    • 头文件
      • ifstream,wifstream从文件读取数据
      • ofstream,wofstream向文件写入数据
      • fstream,wfstream读写文件
    • 头文件
      • istringstream,wistringstream从string读取数据
      • ostringstream,wostringstream向string写入数据
      • stringstream,wstringstream读写string

    类型ifstream和istringstream都继承自istream。

    类型ofsteram和ostringstream都继承自ostream。


    1.2 IO对象不支持拷贝或赋值

    ofstream out1, out2;
    out1 = out2;                        // 错误:不能对流对象赋值
    ofstream print(ofstream);           // 错误:不能初始化ofstream参数
    out2 = print(out2);                 // 错误:不能拷贝流对象 
    
    • 1
    • 2
    • 3
    • 4

    由于不能拷贝流对象,因此我们不能将形参或返回值类型设置为流类型。
    进行IO操作的函数通常以引用方式传递和返回流。
    读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的。


    1.3 条件状态

    IO操作一个与生俱来的问题是可能发生错误。一些错误是可恢复的,而其他错误则发生在系统深处,已经超出了应用程序可以修正的范围。

    IO库条件状态:

    --
    strm::iostatestrm是一种IO类型。iostate是一种机器相关的类型,提供了表达条件状态的完整功能
    strm::badbitstrm::badbit用来指出流已崩溃
    strm::failbitstrm::failbit用来指出一个IO操作失败了
    strm::eofbitstrm::eofbit用来指数流达到了文件结束
    strm::goodbitstrm::gootbit用来指出流未处于错误状态。此值保证为零
    s.eof()若流s的eofbit置位,则返回true
    s.fail()若流s的failbit或badbit置位,则返回true
    s.bad()若流s的badbit置位,则返回true
    s.good()若流s处于有效状态,则返回true
    s.clear()将流s中所有条件状态复位,将流的状态设置为有效。返回void
    s.clear(flags)根据给定flags标志位,将流s中对应条件状态位复位。flags的类型为strm::iostate。返回void
    s.setstate(flags)根据给定的flags标志位,将流s中对应条件状态置位。flags的类型为strm::iostate。返回void
    s.rdstate()返回流s的当前状态,返回值类型为strm::iostate

    一个流一旦发生错误,其上后续的IO操作都会失败。
    只有当流处于无错状态时,我们才可以从它读取数据,向他写入数据。
    代码通常应该在使用一个流之前检查它是否处于良好状态。
    确定一个流对象的状态的最简单的方法是将它作为一个条件来使用:

    while (cin >> word) {
        // ok: 读操作成功...
    }
    
    • 1
    • 2
    • 3

    查询流的状态

    将流作为条件使用,只能告诉我们流是否有效,而无法告诉我们具体发生了什么。
    有时我们也需要知道流为什么失败。例如,在键入文件结束符标识后我们的应对措施,可能与遇到一个IO设备错误的处理方式是不同的。

    IO库定义了一个与机器无关的iostate类型。这个类型应作为一个位集合来使用。
    IO库定义了4个iostate类型的constexpr值,表示特定的位模式。这些值用来表示特定类型的IO条件,可以与位运算符一起使用来一次检测或设置多个标志位。

    • badbit:表示系统级错误,如不可恢复的读写错误。通常情况下,一旦badbit被置位,流就无法再使用了。
    • failbit:在发生可恢复错误后,failbit被置位,如期望读取数值却读出一个字符等错误。这种问题通常是可以修正的,流还可以继续使用。
    • eofbit:如果到达文件结束位置,eofbit和failbit都会被置位。
    • goodbit:值为0,表示流未发生错误。

    如果badbit、failbit和eofbit任一个被置位,则检测流状态的条件会失败。

    标准库还定义了一组函数来查询这些标志位的状态:

    • good():在所有错误位均未置位的情况下返回true
    • bad()、fail()、eof():在对应错误位被置位时返回true。此外,在badbit被置位时,fail()也会返回true。这意味着,使用good()或fail()是确定流总体状态的正确方法。实际上,我们将流当作条件使用的代码就等待于!fail()。而eof和bad操作只能表示特定的错误。

    1.4 管理缓冲输出

    向输出流输出数据时,有可能被操作系统保存在缓冲区中,随后再输出到目标。


    刷新缓冲区:

    • 使用操纵符endl来刷新输出缓冲区
    • 使用操纵符flush和ends刷新输出缓冲区:
      flush刷新缓冲区,但不会输出任何额外字符。ends向缓冲区插入一个空字符,然后刷新缓冲区。

    unitbuf操纵符:
    如果想在每次输出操作之后都刷新缓冲区,我们可以用unitbuf操纵符。它告诉流在接下来的每次写操作之后都进行一次flush操作。而nounitbuf操纵符则重置流,使其恢复正常的系统管理的缓冲区刷新机制。

    默认情况下,对cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的。


    注意:如果程序异常终止,输出缓冲区是不会被刷新的。当一个程序崩溃后,它所输出的数据很可能停留在输出缓冲区中等待打印。


    2. 文件输入输出


    2.1 fstream特有的操作

    除了继承自iostream类型的行为之外,fstream还增加了一些新的成员来管理与流关联的文件。
    我们可以对fstream、ifstream和ofstream对象调用这些操作。


    fstream特有的操作
    --
    fstream fstrm;创建一个未绑定的文件流。fstream是头文件fstream中定义的一个类型。
    fstream fstrm(s);创建一个fstream,并打开名为s的文件。默认的文件模式mode依赖于fstream的类型。
    fstream fstrm(s, mode);与前一个构造函数类似,但按指定mode打开文件。
    fstrm.open(s)打开名为s的文件,并将文件与fstrm绑定。默认的文件mode依赖于fstream的类型。
    fstrm.close()关闭与fstrm绑定的文件。返回void
    fstrm.is_open()返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭。

    成员函数open和close

    如果我们定义了一个空文件流对象,可以随后调用open来将它与文件关联起来:

    ifstream in(ifile);
    ofstream out;                       // 输出文件流未与任何文件关联
    out.open(ifile + ".copy");          // 打开指定文件
    
    • 1
    • 2
    • 3

    如果调用open失败,failbit会被置位。因为调用open可能失败,进行open是否成功的检测通常是一个好习惯:

    if (out) { // 检查open是否成功
        //open成功,我们可以使用文件了
    }
    
    • 1
    • 2
    • 3

    对一个已经打开的文件流调用open会失败,并会导致failbit被置位。随后的视图使用文件流的操作都会失败。为了将文件流关联到另外一个文件,必须首先关闭已经关联的文件:

    in.close();
    in.open(ifile + "2");
    
    • 1
    • 2

    析构

    当一个fstream对象被销毁时,close会自动被调用。


    2.2 文件模式

    文件模式含义
    in以读方式打开
    out以写方式打开
    app每次读写操作前均定位到文件末尾
    ate打开文件后立即定位到文件末尾
    trunc截断文件
    binary以二进制方式打开

    文件模式有如下限制:

    • 只可以对ofstream和fstream对象设定out模式
    • 只可以对ifstream和fstream对象设定in模式
    • 只有当out也被设定时才可以设定trunc模式
    • 只要trunc没有设定,就可以设定app模式。在app模式下,即使没有显示指定out模式,文件也总是以输出方式打开。
    • 默认情况下,即使我们没有指定trunc,以out模式打开的文件也会被截断。为了保留out模式打开的文件内容,我们必须同时指定app模式,或者同时指定in模式。
    • ate和binary可用于任何类型的文件流对象,且可以与其他任何文件模式组合使用。

    默认文件模式:
    每个文件流类型都定义了一个默认的文件模式。
    与ifstream关联的文件默认以in模式打开;与ofstream关联的文件默认以out模式打开;与fstream关联的文件默认以in和out模式打开。


    每次打开文件时,都要设置文件模式,可能时显式地设置,也可能是隐式地设置:

    ofstrean out;
    out.open("test1.txt");                  // 隐含设置为输出和截断
    out.close()
    out.open("test2.txt", ofstream::app);   // 设置为输出和追加
    out.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3. string流

    sstream头文件定义了三个类型来支持内存IO。

    istringstream从string读数据。
    ostringstream向string写入数据。
    stringstream既可以从string读数据也可向string写数据。


    头文件sstream中定义的类型都继承自iostream头文件中定义的类型。
    除了继承得来的操作,sstream中定义的类型还增加了一些特有的操作。


    stringstream的特有操作:

    --
    sstream strm;strm是一个未绑定的stringstream对象。sstream是头文件sstream中定义的一个类型。
    sstream strm(s);strm是一个sstream对象,保存string s的一个拷贝。此构造函数是explict的。
    strm.str()返回strm所保存的string的拷贝
    strm.str(s)将string s拷贝到strm中。返回void

  • 相关阅读:
    算法leetcode|79. 单词搜索(rust重拳出击)
    Uni-App常用事件
    Python3 集合
    Mermaid画流程图可以实现从一条线中间引出另外一条线吗
    Type-C口充电器头为什么没有电压输出?
    入门JavaWeb之 Response 下载文件
    30天入门Python(基础篇)——第1天:为什么选择Python
    【Altium Designer 22原理图,PCB】
    c++踩坑点,类型转换
    3D WEB轻量化引擎HOOPS助力3D测量应用蓬勃发展:效率、精度显著提升
  • 原文地址:https://blog.csdn.net/pengxianchen/article/details/128149106