流(Stream)是C++和C之间的一大区别。写C++的程序员都知道流的用法。在Poco库中,在标准流的基础上又扩充了一些流,分别是基于Base64和HexBinary的编解码流,使用zlib的数据压缩流,二进制的I/O流,文件流,以及一些其他的辅助流;另外Poco库还提供了一个扩展的结构,用于创建用户自定义流。
Poco库中所有的流类都与标准C++库中的流兼容。并且在Poco库中,大多数流都仅仅是个过滤器,这意味着他们不会直接从设备中读取或者写入数据,通常情况下他们会链接到另一个流上。下面我们分别对他们进行介绍。
1、标准C++流介绍
在介绍Poco的流之前,有必要了解C++中的输入输出流,不然会觉得Poco中的流很难理解。在看完C++的流结构后,自然会对Poco库中的流内容豁然开朗。
为了保证语言和平台无关,C++和C一样,不具备内部输入输出能力。语言的输入输出能力是和操作系统相关的,在最底层都是通过调用操作系统的I/O库实现。
在C++的iostream流库中,存在着两个基本部分。分别是:
1、流:C++把输入和输出看作字节流。输入时,程序从输入流中抽取字节;输出时,程序将字节插入到输出流中。流充当了程序和流源或者流目标之间的桥梁。
2、缓冲区:缓冲区是用作中介的内存块,它是将信息从设备传输到程序或者从程序传输到设备的临时存储工具,用以匹配程序和设备之间速度的差距。从设计上说,增加缓冲区,使得C++的iostream结构更具有扩展性。
C++的输入输出类图:
1.1、ios_base
ios_base类封装了C++标准中的流,并定义了在输入输出中不依赖于读写的数据类型基本信息和行为,如格式化信息、异常状态、事件回调等。
在类std::ios_base中,保存了下述关于流的信息:
*格式控制信息的枚举类型fmtflags,影响到如何解释输入串行的格式、如何生成输出串行的格式,例如整数是用16进制还是10进制表示,浮点数是用科学技术法还是定点形式;
*流的状态枚举类型iostate,如数据是否完整、是否到达流的末尾、是否读取失败等;
*流的打开方式枚举类型openmode,如读取、写入、追加、创建时删除原内容、二进制打开;
*流的定位位置枚举类型seekdir,如开始位置、当前位置、结束位置等;
*流的事件枚举类型event,如“擦除”事件erase_event,改变locale设置事件imbue_event,复制格式事件copyfmt_event;
*流的私有的其他额外保存的数据,为一个long型数组与一个指针数组;
*一个成员类failure,用于作为C++标准中,流输入输出类库抛出的各种异常的基类;
*一个成员Init,用于封装cout、cin、wcout等8个静态对象的初始化函数。
成员函数包括:
格式化:
1. 读取/设置流的格式
* fmtflags flags () const;
* fmtflags flags (fmtflags fmtfl);
例子:
1 #include <iostream> 2 3 int main() 4 { 5 std::cout.flags(std::ios::right | std::ios::hex | std::ios::showbase); 6 std::cout.width(10); 7 std::cout << 100 << ‘\n‘; 8 return 0; 9 } 10 11 输出结果: 12 0x64
2. 设置流的格式,与原有格式合并
* fmtflags setf (fmtflags fmtfl);
* fmtflags setf (fmtflags fmtfl, fmtflags mask);
例子:
1 #include <iostream> 2 3 int main() 4 { 5 std::cout.setf(std::ios::hex, std::ios::basefield);// set hex as the basefield 6 std::cout.setf(std::ios::showbase); // activate showbase 7 std::cout << 100 << ‘\n‘; 8 std::cout.unsetf(std::ios::showbase); //deactivate showbase 9 std::cout << 100 << ‘\n‘; 10 return 0; 11 } 12 13 输出结果: 14 0x64 15 64
3. 根据参数mask,清除流的格式的某些位(bit)
* void unsetf (fmtflags mask);
例子:
1 #include <iostream> 2 3 int main() 4 { 5 std::cout.setf(std::ios::hex, std::ios::basefield);// set hex as the basefield 6 std::cout.setf(std::ios::showbase); // activate showbase 7 std::cout << 100 << ‘\n‘; 8 std::cout.unsetf(std::ios::showbase); //deactivate showbase 9 std::cout << 100 << ‘\n‘; 10 return 0; 11 } 12 13 输出结果: 14 0x64 15 64
4. 读取/设置显示浮点数时的精度
* streamsize precision () const;
* streamsize precision (streamsize prec);
例子:
1 #include <iostream> 2 3 int main() 4 { 5 double f = 3.14159; 6 std::cout.unsetf(std::ios::floatfield); //floatfield not set 7 std::cout.precision(5); 8 std::cout << f << ‘\n‘; 9 std::cout.precision(10); 10 std::cout << f << ‘\n‘; 11 std::cout.setf(std::ios::fixed, std::ios::floatfield);//floatfield set to fixed 12 std::cout << f << ‘\n‘; 13 return 0; 14 } 15 16 17 输出结果: 18 3.1416 19 3.14159 20 3.1415900000
5. 读取/设定流的输出数据的显示宽度
* streamsize width () const;
* streamsize width (streamsize wide);
例子:
1 #include <iostream> 2 3 int main() 4 { 5 std::cout << 100 << ‘\n‘; 6 std::cout.width(10); 7 std::cout << 100 << ‘\n‘; 8 std::cout.fill(‘x‘); 9 std::cout.width(15); 10 std::cout << std::left << 100 << ‘\n‘; 11 return 0; 12 } 13 14 输出结果: 15 100 16 100 17 100xxxxxxxxxxxx
语言环境:
1. 给流设置本地语言环境
* locale imbue (const locale& loc);
例子:
1 #include <iostream> 2 #include <locale> 3 4 int main() 5 { 6 std::locale myLocale(""); //get global locale 7 std::cout.imbue(myLocale); //imbue global locale 8 std::cout << 3.14159 << ‘\n‘; 9 return 0; 10 } 11 12 输出结果: 13 3.14159
2. 获取当前使用语言环境
* locale getloc () const;
1.2 basic_ios
basic_ios定义出“与字符类型及其相应字符特性相关”的stream class的共同属性,其中包括流状态、设置流状态、拷贝流标志、返回或设置流缓冲区指针、设置本地化相关信息、返回或设置填充字符、字符转换,还包括了stream所用的缓冲期。
basic_ios在其内部定义了一个指向streambuf的指针。
template<class Elem, class Traits> class basic_ios :public iOS_base { //C++标准库封装了一个缓冲区类streambuf,以供输入输出流对象使用 //每个标准C++输入输出流对象都包含一个指向streambuf的指针 basic_streambuf<_Elem, _Traits> * Mystrbuf; // .... };
成员函数包括:
1. 状态标记函数:
* bool good () const; //检查流状态是否为good
* bool eof () const; //检查流状态位是否为eof,eofbit位被标志
* bool fail () const; //检查流状态位是否为fail,failbit或者badbit被标志
* bool bad () const; //检查流状态是否为bad,badbit位被标志
* iostate rdstate () const ; //返回流状态位
有两种方法可以获得输入/输出的状态信息。一种方法是通过调用rdstate()函数,它返回当前状态的错误标记。另一种方法则是使用good(),eof(),fail(),bad()函数来检查相应的输入/输出状态。