C++ 基础与深度分析 Chapter7 深入I/O(文件与内存操作、流的状态、流的定位、流的同步)

文件与内存操作

文件

在这里插入图片描述

cin和cout是与终端的交互。cpp的I\O流,还能对文件和内存进行操作。
文件操作主要使用了3个类模版:basic_ifstream输入, basic_ofstream输出, basic_fstream打开一个文件,同时接受输入和输出2种操作。
在这里插入图片描述

#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;


int main()
{
    std::ofstream outFile("Myfile");
    outFile << "Jammy & Kin !\n";
}
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;


int main()
{
    std::ofstream outFile;
    cout << outFile.is_open() << endl; // 0
    outFile.open("Myfile");
    cout << outFile.is_open() << endl; // 1
    outFile.close();
    cout << outFile.is_open() << endl; // 0
}

#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;


int main()
{
    std::ofstream outFile;
    cout << outFile.is_open() << endl; // 0
    outFile.open("Myfile");
    outFile << "Jammy!\n"; // 系统已开始不写到文件里,而是写到缓存里
    outFile.close(); // close时,系统将缓存的内容放到文件里
    // 如果没有close,系统会根据机制,自动关闭。我们一般构造一个语句体(域),让它自动销毁


    std::ifstream inFile("Myfile"); // 文件名称
    std::string x;
    inFile >> x; // 等待x的输入
    cout << x << endl; // 将x的内容打到终端里 
}

通常in和out打开文件,光标都是在最开头。ate就是让光标放在最后。
ate和app不一样的地方是,ate开始在文件末尾,可以移动到文件当中某一个位置。app只能放在文件的末尾,不同移到中间。
trunc: 打开文件是用来写的,并且把文件之前的内容删除掉。
binary: 能禁止系统特定的转换。
在这里插入图片描述

#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;

int main()
{
    // 把文件之前的内容删除,添加新的内容
    std::ofstream outFile("Myfile", std::ios_base::out | std::ios_base::trunc);
    outFile << "Hello World";
}

内存

在这里插入图片描述
basic_istringsteam: 读取数据
basic_ostringstream: 写入数据
basic_stringstream: 读写
在这里插入图片描述

#include <iostream>
#include <sstream>
using namespace std;

int main()
{
    std::ostringstream obj1;
    obj1 << 1234; // obj1内存流对象,把1234整数写入,将整数转成了字符串
    auto res = obj1.str(); // res获取底层对应的内存,res类型是std::string
    cout << res << endl; // 1234,注意这里已经不是上面的1234整数了,而是一个字符串
}
#include <iostream>
#include <sstream>
using namespace std;

int main()
{
    std::ostringstream obj1;
    obj1 << 10; 
    std::string res = obj1.str();
    std::istringstream obj2(res); //构造输入流,把读取的res内存读出来
    int x;
    obj2 >> x;
    cout << x << endl; // 10 obj2从res读取1和0,在内部完成解析,将1和0解析,然后存在int x中,输出
}

内存流也会受到打开流的影响,但是没有trunc和binary。

int main()
{
    std::ostringstream buf2("test", std::ios_base::ate);
    buf2 << 1;
    cout << buf2.str() << endl; // test1
}
int main()
{
    std::ostringstream buf2("test"); // ate去掉
    buf2 << 1;
    cout << buf2.str() << endl; // 1est
}
int main()
{
    std::ostringstream buf2("test", std::ios_base::app);
    buf2 << 1;
    cout << buf2.str() << endl; // test1 str返回是cpp类型的字符串
}

在这里插入图片描述
在这里插入图片描述
基于字符串流的字符串拼接优化

#include <iostream>
#include <sstream>
using namespace std;

int main()
{
    std::string x;
    x += "Hello";
    x += " world";
    x += " Jammy";
    x += " Kin";
    // 这样性能比较差,先看string是否有足够的缓冲区足够保存新的字符串。
    // 将原有的stirng拷贝新的缓冲区,加上新的string,再把原缓冲区释放
    // 内存的不断地开辟和释放,非常耗时
    cout << x << endl; 

    // 等价于下面的代码
    std::ostringstream obj;
    obj << "Hello";
    obj << " world";
    obj << " Jammy";
    obj << " Kin";
    cout << obj.str() << endl; // 基于字符串流的字符串拼接优化,缓存满了,一次性刷新
}

流的状态

在这里插入图片描述
流的状态:正常状态,还是异常的状态。
刚开始使用流,都是正常的,但是随着插入或者提取,可能会失败,就是异常的状态。
在这里插入图片描述
badbit

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    std::ofstream outFile;
    outFile << 10; // 流的异常状态,会产生badbit(不可恢复的流错误)
}

输入流的failbit

int main()
{
    int x;
    cin >> x; // 如果输入“Hello”,这样读取就失败了,cin就是failbit
}

输出流的failbit

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    std::ofstream outFile;
    outFile.close(); //这里outFile本身没有关联任何文件,是关闭状态,调用close再关闭,就会产生failbit。
}

failbit是一种可以恢复的错误,不同于badbit。
eofbit:(end of file)文件末尾,无法再读取。对于内存流和终端流都是有效的。

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    int x;
    cin >> x; // 1
    cout << std::cin.good() // 1
         << std::cin.bad() // 0
         << std::cin.fail() // 0
         << std::cin.eof() // 0
         << endl;
}
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    int x;
    cin >> x; // abc
    cout << std::cin.good() // 0
         << std::cin.bad() // 0
         << std::cin.fail() // 1
         << std::cin.eof() // 0
         << endl;
}

在这里插入图片描述
在这里插入图片描述
通常,我们不给流设置复位。clear和setstate。
在这里插入图片描述

流的定位

在这里插入图片描述
流是一长串,那么往哪里进行写入和读取,这就需要流的定位。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
seekg()和seekp(),都是覆盖操作,而不是插入操作。
在这里插入图片描述
seekg有2个方法。重载了。
在这里插入图片描述
在这里插入图片描述

流的同步

在这里插入图片描述
flush,将缓冲区内容扔到外部设备里,将缓冲区内容清空。
在这里插入图片描述

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    cout << "What's your name \n"; // 如果这句话没占满缓冲区,下面等待用户输入,就在缓冲区里放着
    // 我们希望在等待用户输入之前,就把句子打出来
    // std::endl和std::flush 都可以
    cout.flush();
    std::string name;
    cin >> name;
}

在这里插入图片描述
sync可以选择清空缓冲区或者重新填充它。具体做哪个,库函数自己决定的。
在这里插入图片描述
unitbuf,单位缓冲区。本质含义是写入要大于等于1个字符,也就是只要写一个东西,就从缓冲区放到终端里。因为缓冲区太小了,就1个字符。好处是信息立即存入终端,坏处是效率的降低。
在这里插入图片描述
2个流(输入/输出)绑定到1个输出流。既可以多对一,但是不能一对多。A不可以既绑定输出流C,又绑定输出流D。
在这里插入图片描述
c++和c语言输入和输出函数同步,这样的同步一定是有成本的,效率一定是降低的。可以通过sync_with_stdio关闭。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
因为解除了同步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值