IO类
为了支持不同种类的IO操作,除了istream和ostream之外,标准库还制定了一些其他的IO类型
头文件iostream
// w开头表示宽字符版对象
istream wistream //从流中读取数据
ostream wostream //向流中写数据
iostream wiostream //读写流
头文件fstream
// w开头表示宽字符版对象
ifstream wifstream //从文件读取数据
ofstream wofstream //向文件写数据
fstream wfstream //读写文件
头文件sstream
// w开头表示宽字符版对象
istringstream wistringstream //从string中读取数据
ostringstream wostringstream //向string中写数据
stringstream wstringstream //读写string
IO类型之间的关系
概念上设备类型和字符大小都不会影响我们要执行的IO操作,例如我们可以用 >> 读取数据,而不用管是从一个控制台窗口,一个磁盘文件,还是一个string读取。类似的,我们也不用管读取的字符能存入一个 char 对象内,还是需要一个 wchar_t 对象来存储。标准库使我们能忽略这些不同类型流的差异,这是通过继承机制实现的。
类型 ifstream 和 istringstream 都是继承自 istream 的,因此我们可以像使用 istream 一样来使用 ifstream 和 istringstream,也就是说我们如何使用 cin 的,就能同样的使用这些类型的对象。
IO对象无拷贝或赋值
我们不能拷贝或者对IO对象赋值
ofstream out1, out2;
out1 = out2; //错误,不能对流对象赋值
ofstream print(ofstream); //错误,不能初始化ofstream对象
out2 = print(out) //错误,不能拷贝流对象
由于不能拷贝流对象,因此我们也不能将形参或者返回类型设置为流类型,通常是以引用方式传递和返回流,读写一个流对象会改变其值,因此这种引用不能是const的
条件状态
IO操作有时可能会发生错误,下面列出了一些IO类定义的函数和标志,可以帮助我们访问和操纵流的条件状态
函数标志 | 含义 |
---|---|
strm::iostate | 机器相关类型,提供了表达条件状态的完整功能 |
strm::badbit | 用来指出流已崩溃 |
strm::falibit | 指出一个IO操作失败了 |
strm::eofbit | 指出流已到达文件结束 |
strm::goodbit | 用来指出流未处于错误状态。此值保证为0 |
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) | 根据给定的flag标志位,将s对应状态位复位,falg的类型为strm::iostate,返回void |
s.rdstate() | 返回流当前状态,返回类型为strm::iostate |
文件输入输出
头文件fstream
定义了三个类型来支持文件IO:
ifstream
从一个给定文件读取数据;
ofstream
向一个给定文件写数据;
fstream
从一个给定文件读写数据;
这些类型都是继承自iostream,因此我们可以像cin,cout一样操作这些类型,特别的我们可以用 >> 和 << 来读写文件,还可以使用getline从一个ifstream读取数据。
下表列出了一些fstream的特有操作
操作 | 含义 |
---|---|
fstream fstrm | 创建一个未绑定的文件流。fstream是头文件fstream中定义的一种类型 |
fstream fstrm(s) | 创建一个fstream,并且打开文件名为s的文件。s可以是string类型,或者是一个指向c风格字符串的指针 |
fstream fstrm(s,mode) | 按指定mode打开文件 |
fstrm.open(s) | 打开名为s的文件,并且将文件与fstrm绑定。s可以是一个指向c风格字符串的指针或是string类型,返回void |
fstrm.close(s) | 关闭fstrm绑定的文件,返回void |
fstrm.is_open(s) | 返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭 |
文件模式mode
模式 | 含义 |
---|---|
in | 以读方式打开 |
out | 以写方式打开 |
app | 每次写操作前均定位到文件末尾 |
ate | 打开文件后立即定位到文件末尾 |
trunc | 截断文件 |
binary | 以二进制方式进行IO |
限制
- 只可以对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打开。
文件流对象的使用
// read函数
istream &read(istream &is, Sales_data &item)
{
double price=0;
is >> item.bookNO >> item.units_sold >> price;
item.revenue = price*item.units_sold;
return is;
}
// print函数
ostream &print(ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
ifstream input(argv[1]); //打开销售记录文件
ofstream output(argv[2]); //打开输出文件
Sales_data total;
if (read(input, total))
{
Sales_data trans;
while(read(read, trans)){
if (total.isbn() == trans.isbn()){
total.combine(trans);
}
else{
print(output, total) << endl; //向输出文件写入数据
total = trans;
}
}
print(output, total) << endl; //向输出文件写入数据
}else
cerr << "No data?" << endl;
string流
头文件sstream
定义了三个类型来支持文件IO:
istringstream
从一个给定string读取数据;
ostringstream
向一个string写数据;
stringstream
从一个string读写数据;
特有操作
操作 | 含义 |
---|---|
sstream strm | 定义一个未绑定的sstring对象 |
sstream strm(s) | strm是一个sstring对象,保存string s的一个拷贝 |
strm.str() | 返回strm保存的string拷贝 |
strm.str(s) | 将string s拷贝到strm中,返回void |
用法
string s,a;
getline(cin, s);
istringstream record(s);
while (record >> a)
cout << a << endl;