C++中的IO库概述及操作笔记
来源:互联网 发布:mxnet 安装 windows 编辑:程序博客网 时间:2024/05/17 22:39
C++中的IO库概述及操作笔记
- C中的IO库概述及操作笔记
- IO类
- IO类继承关系
- 条件状态
- 输出管理
- 冲刷缓冲区
- unitbuf操作符
- 绑定输入和输出流对象
- 文件IO
- 初始化
- 文件模式
- string流
- C风格IO
- 总结
- IO类
C++包括两类IO库,一种是基于流形式的IO库,另一种是C风格的IO函数库,下面我会分别来阐述,重点还是放在C++的流形式IO上。
IO类
IO类继承关系
基于流的输入和输出围绕抽象的输入输出设备组织而成,这些抽象输入输出设备包括控制台窗口,文件和内存中的string对象,并且这些类都是模板化的,类的继承形式如下:
C++的IO类继承架构图
在上面的继承关系图中,ios_base是接口类,主要管理格式符号和输入输出异常,通常我们不对其进行直接操作,我们需要使用基类时也是使用basic_ios,用其来管理任意的流操作。不过我们在日常使用中,不会直接使用上图中的类名,而是通过了别名来进行调用,别名的用法如下代码所示,其中以w开头的都是宽字符类型使用的。在IO流的使用中,一定要注意的是不能够使用拷贝构造和赋值语句,因为在基类中这些函数就已经被私有化了。还有两个库iomanip和stdiostream需要关注,前者声明了格式化IO的一些操作,后者用于混合使用C和C++的IO机制。
/* Defined in header <ios> */typedef basic_ios<char> ios;typedef basic_ios<wchar_t> wios;/* Defined in header <streambuf> */typedef basic_streambuf<char> streambuf;typedef basic_streambuf<wchar_t> wstreambuf;/* Defined in header <fstream> */typedef basic_filebuf<char> filebuf;typedef basic_filebuf<wchar_t> wfilebuf;/* Defined in header <sstream> */typedef basic_stringbuf<char> stringbuf;typedef basic_stringbuf<wchar_t> wstringbuf;/* Defined in header <istream> */typedef basic_istream<char> istream;typedef basic_istream<wchar_t> wistream;/* Defined in header <ostream> */typedef basic_ostream<char> ostream;typedef basic_ostream<wchar_t> wostream;/* Defined in header <istream> */typedef basic_iostream<char> iostream;typedef basic_iostream<wchar_t> wiostream;/* Defined in header <fstream> */typedef basic_ifstream<char> ifstream;typedef basic_ifstream<wchar_t> wifstream;typedef basic_ofstream<char> ofstream;typedef basic_ofstream<wchar_t> wofstream;typedef basic_fstream<char> fstream;typedef basic_fstream<wchar_t> wfstream;/* Defined in header <sstream> */typedef basic_istringstream<char> istringstream;typedef basic_istringstream<wchar_t> wistringstream;typedef basic_ostringstream<char> ostringstream;typedef basic_ostringstream<wchar_t> wostringstream;typedef basic_stringstream<char> stringstream;typedef basic_stringstream<wchar_t> wstringstream;
我们平时接触最多的还是标准库中已经被预定义的cin(wcin),cout(wcout),cerr(wcerr),clog(clog),他们分别对应着标准输入流,标准输出流,标准错误输出流和标准日志输出流,不过可以通过rdbuf()方法来改变这些流对象的缓冲区,也就改变了这些流对象的标准功能,注意cerr流无缓冲区。
条件状态
在流对象中有一个非常重要的特性是条件状态,通过该特性我们可以了解一个流对象的当前状态以及是否能正常工作,因为当一个错误发生时,该流对象随后的操作就必然会失败。所有的流对象都有如下四种条件状态:goodbit,badbit,eofbit,failbit。goodbit代表流对象正常,badbit代表该流对象崩溃了,不可恢复,eofbit表示该流对象已经处于流的结束位置,failbit表示某次IO操作失败,但该错误可恢复。同时还提供了一些方法如eof(),fail(),bad(),good(),clear(),setstate(),rdstate()等来对条件状态进行判断和操作。我们以一段代码来说明如何使用这些方法:
#include<string>#include<sstream>#include<iostream>using namespace std;int main(int argc, char* argv[]){ string obj{"just a test!"}; stringstream ss(obj); stringstream::iostate state = ss.rdstate(); /* 读取该流对象中的条件状态 */ ss.setstate(state | stringstream::failbit); /* 将该流对象的failbit置位 */ string tmp; while(ss>>tmp) /* 因为错误存在,该流对象不会输入 */ { cout<<tmp<<endl; } if(ss.fail()) cout<<"true"<<endl; string obj2{"another test!"}; ss.str(obj2); /* 更换该流对象的BUFFER */ ss.clear(); /* 使该流对象有效 */ while(ss>>tmp) { cout<<tmp<<endl; } if(ss.eof()) cout<<"true"<<endl; return 0;}
结果:
true
another
test!
true
接下来我用一个表格来说明条件状态位与条件判断方法的关系:
可见fail()方法和operator !是作用等价的,而operator bool是与fail()方法作用相反。
输出管理
每一个输出流对象都管理一个缓冲区,这是因为IO操作非常耗时,由于该缓冲区的存在,流对象会将输出都先存放在缓冲区中,等到满足下列条件之一满足后再一起输出,在我们的日常编程中,根据需求可能需要对输出时机进行管理,故针对以下条件提供几种管理输出的方法。
- 程序正常完成,如return;
- 缓冲区已满;
- 显性出现操作符endl;
- 使用操作符unitbuf设置缓冲区中间状态为空;
- 输出流对象与其他输入或输出流对象进行了绑定。
前面两种条件由程序自己判断,下面三种条件可在程序编写过程对输出进行管理。
冲刷缓冲区
cout<<"hi!"<<endl; /* 跳转下一行 */cout<<"hi!"<<flush; /* 不添加数据 */cout<<"hi!"<<ends; /* 末尾添加null */cout.flush();
unitbuf操作符
cout<<unitbuf; /* 每次输出都冲刷缓冲区 */cout<<nounitbuf; /* 正常缓冲 */
绑定输入和输出流对象
cin.tie(&cout); /* 将标准输入和标准输出进行绑定,每次输入都将冲刷输出缓冲区 */ /* 一个流对象只能绑定一个流对象,当一个流对象可以被多个流对象绑定 */
文件IO
初始化
文件流对象有两种初始化形式,第一种是利用构造函数,直接在实例化一个文件流对象时就赋给其一个文件名,第二种则是使用open()方法,在实例化一个文件流对象后再显式调用open()方法打开一个文件,文件流对象在作用域结束时会自动调用析构函数释放该文件,但是如果在作用域内需要另外一个文件流对象去对同一个文件进行操作,则需要第一个文件流对象显式调用close()方法释放该文件,一个文件同一时间只能被一个文件流对象访问。利用is_open()方法可以判断一个文件流对象是否打开了一个文件。
#include <string>#include <fstream>#include <iostream>using namespace std;int main(int argc, char* argv[]){ string filename = "example.123"; fstream fs; fs.open(filename); if(!fs.is_open()) /* 文件可能不存在 */ { fs.clear(); /* 清除失败状态 */ fs.open(filename, ios::out); /* 创建文件 */ fs.close(); fs.open(filename); } cout<<boolalpha; cout<<"fs.is_open() = "<<fs.is_open()<<endl; cout<<"fs.good() = "<<fs.good()<<endl;}
结果:
true
true
文件模式
string流
string流对象是使用string对象作为缓冲区,可以将string中的内容输出或输入到其他类型的对象中。string流对象可以在实例化时用一个string对象进行构造,也能够在实例化后用str()方法载入新的string对象,其他操作方法与文件流对象类似。string流对象的一个优点是自动进行类型转化:
#include<string>#include<sstream>using namespace std;int main(int argc, char* argv[]){ string str{"123 5.89 false"}; stringstream ss(str); int inttmp; double doubletmp; bool booltmp; ss>>inttmp; ss>>doubletmp; ss>>booltmp; cout<<inttmp<<'\t'<<doubletmp<<'\t'<<booltmp<<endl; return 0;}
结果:
123 5.89 0
C风格IO
C风格的IO由一系列函数组成,对FILE结构指针指向的文件或者对象来进行操作,该系列函数都在<\cstdio>中被声明。
文件访问类
fopen、freopen、fclose、fflush、fwide、setbuf、setvbuf
直接输入输出类
fread、fwrite
非格式化输入输出
字节/字符串
fgetc/getc、fgets、fputc/putc、fputs、getchar、gets、putchar、puts、ungetc
格式化输入输出
字节/字符串
scanf/fscanf/sscanf、vscanf/vfscanf/vsscanf、printf/fprintf/sprintf/snprintf、vprintf/vfprintf/vsprintf/vsnprintf
文件位置
ftell、fgetpos、fseek、fsetpos、rewind
错误处理
clearerr、feof、ferror、perror
文件操作
remove、rename、tmpfile、tmpnam
总结
- iostream类处理到控制台的IO
- fstream类处理文件的IO
- stringstream类处理到内存中string对象的IO
fstream和stringstream类继承于iostream类,ifstream和istringstream类继承于istream类,ofstream和ostringstream类继承于ostream类。每个IO对象都有一系列的条件状态来表明是否能够被执行。如果一个错误发生,流对象将不会有进一步的输入或者输出,直到问题被解决,状态复位。同时,标准IO库也提供了一系列的函数来设置和测试这些状态。
PS:本文还有一批IO操作符,流对象的缓冲以及更为具体的IO流对象的方法没有涉及,所以本文仍然会继续进行补充和拓展。本文的不足之处和因为笔者知识缺陷导致的错误还请读者指出来,谢谢
- C++中的IO库概述及操作笔记
- C中的文件与IO操作
- C文件IO操作函数笔记。
- IO操作用法简单概述
- C#中的文件的IO原理及操作
- java中的io系统总结及一些常用的操作
- C中的文件与IO操作(一)
- java中的IO操作(一)【个人笔记】
- java中的IO操作(二)【个人笔记】
- Lua学习笔记:Lua 中的C Api 概述
- C标准库之文件IO操作
- MFC中的IO操作
- Java中的IO操作
- JAVA中的IO操作
- java中的IO操作
- java中的IO操作
- java中的IO操作
- JAVA 中的IO操作
- 237. Delete Node in a Linked List
- 浅谈单片机应用程序架构
- 插入排序之python实现
- test
- 一些关于UIView的 方法,持续增加
- C++中的IO库概述及操作笔记
- top k
- C# 使用AD(Active Directory)验证内网用户名密码
- android内存泄漏-1
- 缝隙天线
- CSDN博客中编辑公式
- 【原创】东方耀reactnative 视频16,17之-TextInput组件
- druid连接池
- UIView添加手势 然后UITableView 添加进这个View 导致UITableView 的单元格点击事件无效