1. 无论是设备的类型还是字符的大小,都不影响需要执行的IO操作。
2. IO类型:(读写char类型组成的流)
- iostream: 读写控制窗口类型
- fstream : 读写已命名文件的类型
- stringstream: 读写存储在内存中的string对象
3. 如果函数有基类类型的引用形参时,可以给函数传递其派生类对象。
因为IO通过继承关联,所以可以只编写一个函数,而将它应用到三种类型的流上:控制台、磁盘文件、字符串流。
4. 国际字符串的支持
- 每个类都加上‘w’前缀来读写 wchar_t 的数据,wostream, wistream, wiostream, wifstream, ...wistringstream
- 每个对象加上'w'前缀,wcin, wcout, wcerr
5. IO对象不可复制或赋值
ofstream out1, out2;
out1 = out2; //不能赋值
//只有支持复制的元素类型可以存储在vector或其他容器类型里。
ofstream print(ofstream);
out2 = print(out2); //不能复制
//形参或返回类型不能为流类型,如果需要传递或返回IO对象,必须传递或返回指向该对象的指针或引用。
ofstream &print(ofstream&); //ok
while(print(out2)) //ok
//IO对象的读写会改变它的状态,因此引用必须是非const的。
流必须处于无错误状态,才能用于输入输出。检测流是否可用的最简单的方法是检查其真值。
s.eof() | 是否达到文件尾 |
s.fail() | 发生了可恢复的错误 |
s.bad() | 发生系统级别的错误,不可恢复 |
s.good() | 上面三个没有一个为true,good为true,也就是流是正常状态 |
s.clear() | 将s中所有状态值设为有效 |
s.clear(flag) | 将s某个指定条件状态设置为有效,flag类型是strm::iostate |
s.setstate(flag) | 给流s添加指定条件,可打开某个指定的条件,用于表示某个问题的发生 |
s.rdstate() | 返回流s的当前条件 |
strm::iostate | |
strm::badbit | |
strm::failbit | |
strm::eofbit | 在遇到文件结束符时设置的,此时同时还设置了failbit |
7. 流状态的查询和控制
while(cin >> ival, !cin.eof())
//上面条件的逗号表达式表示,首先计算每个操作数,然后返回最右边操作数作为整个逗号表达式的结果
8. 条件状态的访问
istream::iostate old_state = cin.rdstate();
cin.clear();
process_input();
cin.clear(old_state);
is.setstate(ifstream::badbit | ifstream::failbit); //设置bad和fail位打开状态,其他位则为0
9. 输出缓冲区管理:以下将导致缓冲区的内容被刷新
- 程序正常结束,清空所有输出缓冲区
- 在一些不确定的时候,缓冲区满了,此时,缓冲区将在写下一个值之前刷新
- 用操纵符显示刷新,如行结束符endl,flush(刷新流但不添加任何字符),ends(插入空字符null,然后刷新它)
- 每次输出操作执行完后,用unitbuf操纵符设置流的内部状态,从而清空缓冲区
- 将输出流与输入流关联(tie)起来,此时,在读输入流时,将刷新其关联的输出缓冲区
10. unitbuf 操纵符
cout << unitbuf << "first" << "second"<< nounitbuf;
等价于
cout << "first" << flush << "second" << flush;
//nounitbuf操纵符,将流恢复为使用正常的、由系统管理的缓冲区刷新方式
11. 将输入和输出绑在一起
cin.tie(&cout);
ostream *old_tie = cin.tie();
cin.tie(0); //传参数0,表示打破该流上已存在的捆绑
cin.tie(&cerr);
cin.tie(0);
cin.tie(old_tie); //重建old_tie保存的捆绑
12. 文件流对象的初始化
ifstream infile(ifile.c_str());
ofstream outfile(ofile.c_str()); //文件名使用C风格字符串
等价于
ifstream infile;
ofstream outfile;
infile.open("in");
outfile.open("out");
if(infile) //打开成功则进入if判断
ifstream input;
vector<string>::const_iterator it = files.begin();
while(it != files.end())
{
input.open(it->c_str());
if(!input)
break;
while(input >> s)
process(s);
input.close();
input.clear();
++it;
}
15. 文件模式
out、app、trunc只能用ofstream或fstream对象;
in模式只能用ifstream或fstream对象
in | 打开文件做读操作 ifstream打开时默认的模式 |
out | 打开文件做写操作 ofstream打开时默认的模式,其实同时指定了trunc模式 |
app | 在每次写之前找到文件尾 如需要打开文件时,原来内容不被清空,需要显示指定app,或者fstream同时指定in和out模式 |
ate | 打开文件后,立即将文件定位在文件尾 (只在打开时有效) |
trunc | 打开文件时,清空已存在的文件流 |
binary | 以二进制模式进行IO操作 (将文件以字节序列的形式处理,而不解释流中的字符) |
ofstream outfile("file1"); //打开文件时,原来的内容清空
ofstream outfile2("file1", ofstream::out | ofstream::trunc);
ofstream appfile("file2", ofstream::app);//原来文件中的内容没有被清空
fstream 默认打开的方式是in | out ,这种情况下不会清空原来文件中的内容。
模式是文件的属性,而不是流的属性
16. 一个打开并检查输入文件的程序
ifstream& open_file(ifstream& in, const string& filename)
{
in.close();
in.clear();
in.open(filename.c_str());
return in;
}
17. 字符串流stringstream特定的操作
stringstream strm; | 创建自由的stringstream对象 |
stringstream strm(s); | 创建存储s的副本的stringstream对象,s是string类型的对象 |
strm.str() | 返回strm中存储的string类型对象 |
strm.str(s) | 将string类型的s复制给strm,返回void |
18. stringstream对象的使用
string line, word;
while(getline(cin, line))
{
istringstream stream(line);
while(stream >> word)
{
....
}
}
19. stringstream提供的转换和格式化
int val1=512, val2=1024;
ostringstream format_message;
format_message << "val1:" << val1 << "\n"
<< "val2:" << val2 << "\n";
//为了读取input_string, 必须把该string对象分解为若干个部分。我们要的是数值型数据;为了得到它们,必须读取(和忽略)处于所需数据周围的标号。
istringstream input_string(format_message.str());
string dump;
input_string >>dump>>val1>>dump>>val2;
cout << val1<<" " <<val2 << endl;//因为空白符会被忽略,所以上面的“\n”会被忽略