The IO Library标准 IO 库
8.1 An Object-Oriented Library
标准IO库实际上是针对三类流stream的操作
stream
|
Header
|
Type
|
|
console
|
iostream
|
istream
ostream
iostream
|
提供
char
wchar_t
cin
wcin
…
|
string stream
|
sstream
|
istringstream
ostringstream
stringstream
|
file
|
fstream
|
ifstream
ofstream
fstream
|
对于IO对象来说是不能拷贝或赋值的,因此这些写法都是会死人的:
ofstream out1, out2;
out1 = out2; // error: cannot assign stream objects
ofstream print(ofstream);
out2 = print(out2); // error: cannot copy stream objects,形参不能是IO类型
|
l 形参不能是IO类型。返回值也不能是IO类型。
l IO对象也不能保存在vector这样的集合容器里。
8.2 条件状态Condition States
条件状态成员是做什么用的?
是用来详细地描述当前的流(stream)的状态。例如:是否可用,或者遇到了某种特殊的错误。这些状态信息即可以访问,也可以设置。
每个流对象(stream object)都会包含一个成员(member),这个成员通过setstate和clear操作进行管理。它的类型是iostate。
每个 IO 类还定义了三个 iostate 类型的常量值,分别表示特定的位模式。
strm::badbit:badbit 标志着系统级的故障,如无法恢复的读写错误。
strm::failbit:如果出现的是可恢复的错误,如在希望获得数值型数据时输入了字符,此时则设置 failbit 标志。
strm::eofbit:是在遇到文件结束符时设置的,此时同时还设置了 failbit。
对于IO类的条件状态的操作,不管是查询的,eof(),fail(),bad(),还是赋值操作,clear(),setstate(),应该都是位操作。
8.3 管理输出缓冲 Managing the Output Buffer
哪些条件下buffer会被清空?
1. The program completes normally. All output buffers are emptied as part of the return from main.
程序正常结束。作为 main 返回工作的一部分,将清空所有输出缓冲区。
2. At some indeterminate time, the buffer can become full, in which case it will be flushed before writing the next value.
在一些不确定的时候,缓冲区可能已经满了,在这种情况下,缓冲区将会在写下一个值之前刷新。
3. We can flush the buffer explicitly using a manipulator such as endl, flush, ends.
用操纵符显式地刷新缓冲区,例如行结束符 endl。
4. We can use the unitbuf manipulator to set the stream's internal state to empty the buffer after each output operation.
在每次输出操作执行完后,用 unitbuf 操作符设置流的内部状态,从而清空缓冲区。
5. We can tie the output stream to an input stream, in which case the output buffer is flushed whenever the associated input stream is read.
可将输出流与输入流关联(tie)起来。在这种情况下,在读输入流时将刷新其关联的输出缓冲区。
程序崩溃时,缓冲区是不会被刷新的
前提:如果程序非正常结束,输出缓冲(Output buffer)是不会刷新的。
建议:在每个输出都用endl的结尾。
关于endl和"n的区别?
如果简单的从输出上看,二者肯定是没有区别的。但是endl会刷新输出cout的buffer。
输入流和输出流绑定
cin和cout绑定
结果是:任何读输入流的尝试都将首先刷新与之绑定的输出流的缓冲区(buffer)。:
cin.tie(&cout);
cin.tie(0); //break tie to cout, cout no longer flushed when cin is read
|
交互系统一定要保证输出流和输入流是绑定在一起的。
8.4 文件输入和输出 File Input and Output
fstream header
l ifstream
l ofstream
l fstream
基本语法格式:
// construct an ifstream and bind it to the file named ifile
ifstream infile(ifile.c_str());
// ofstream output file object to write file named ofile
ofstream outfile(ofile.c_str());
|
注意:文件名要使用C风格的字符串。
文件流可以和文件重新绑定
l 文件流可以和文件重新绑定。但是在重新绑定前要先关闭流,并清空文件流的状态,否则上一次的文件流的状态就会是重新绑定后的初始状态。
l 关闭流对象,都不可能改变流对象内部的状态。Closing a stream does not change the internal state of the stream object.
文件模式
ios_base::openmode
truncate
当文件打开时清空文件的所有内容,如果使用这个属性对文件至少要有写入的权限
Sample:
// opens in binding it to the given file
ifstream& open_file(ifstream &in, const string &file)
{
in.close(); // close in case it was already open
in.clear(); // clear any existing errors
// if the open fails, the stream will be in an invalid state
in.open(file.c_str()); // open the file we were given
return in; // condition state is good if open succeeded
}
|
这是一个标准的文件重新绑定的代码,包括了以上的注意事项。
8.5 字符串流String Streams
字符串流和文件流其实很类似。独有的就是利用字符串流来实现格式化输入/输出。
输出
int val1 = 512, val2 = 1024;
ostringstream format_message;
// ok: converts values to a string representation
format_message << "val1: " << val1 << ""n"
<< "val2: " << val2 << ""n";
|
输入:
// str member obtains the string associated with a stringstream
istringstream input_istring(format_message.str());
string dump; // place to dump the labels from the formatted message
// extracts the stored ascii values, converting back to arithmetic types
input_istring >> dump >> val1 >> dump >> val2;
cout << val1 << " " << val2 << endl; // prints 512 1024
|