POCO C++庫學習和分析 -- 流 (一)
流(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++的輸入輸出類圖:
下面對C++中各個流類的介紹主要來自於wiki以及網站cplusplus。
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. 讀取/設置流的格式
[cpp]
fmtflags flags() const;
fmtflags flags (fmtflags fmtfl);
fmtflags flags() const;
fmtflags flags (fmtflags fmtfl); 例子:
[cpp]
// modify flags
#include <iostream> // std::cout, std::ios
int main () {
std::cout.flags ( std::ios::right | std::ios::hex | std::ios::showbase );
std::cout.width (10);
std::cout << 100 << '\n';
return 0;
}
// modify flags
#include <iostream> // std::cout, std::ios
int main () {
std::cout.flags ( std::ios::right | std::ios::hex | std::ios::showbase );
std::cout.width (10);
std::cout << 100 << '\n';
return 0;
}
2. 設置流的格式,與原有格式合並
[cpp]
fmtflags setf (fmtflags fmtfl);
fmtflags setf (fmtflags fmtfl, fmtflags mask);
fmtflags setf (fmtflags fmtfl);
fmtflags setf (fmtflags fmtfl, fmtflags mask); 例子:
[cpp]
// modifying flags with setf/unsetf
#include <iostream> // std::cout, std::ios
int main () {
std::cout.setf ( std::ios::hex, std::ios::basefield ); // set hex as the basefield
std::cout.setf ( std::ios::showbase ); // activate showbase
std::cout << 100 << '\n';
std::cout.unsetf ( std::ios::showbase ); // deactivate showbase
std::cout << 100 << '\n';
return 0;
}
// modifying flags with setf/unsetf
#include <iostream> // std::cout, std::ios
int main () {
std::cout.setf ( std::ios::hex, std::ios::basefield ); // set hex as the basefield
std::cout.setf ( std::ios::showbase ); // activate showbase
std::cout << 100 << '\n';
std::cout.unsetf ( std::ios::showbase ); // deactivate showbase
std::cout << 100 << '\n';
return 0;
}輸出:
Output:
0x64
64
3. 根據參數mask,清除流的格式的某些位(bit)
[cpp]
void unsetf (fmtflags mask);
void unsetf (fmtflags mask); 例子:
[cpp]
// modifying flags with setf/unsetf
#include <iostream> // std::cout, std::ios
int main () {
std::cout.setf ( std::ios::hex, std::ios::basefield ); // set hex as the basefield
std::cout.setf ( std::ios::showbase ); // activate showbase
std::cout << 100 << '\n';
std::cout.unsetf ( std::ios::showbase ); // deactivate showbase
std::cout << 100 << '\n';
return 0;
}
// modifying flags with setf/unsetf
#include <iostream> // std::cout, std::ios
int main () {
std::cout.setf ( std::ios::hex, std::ios::basefield ); // set hex as the basefield
std::cout.setf ( std::ios::showbase ); // activate showbase
std::cout << 100 << '\n';
std::cout.unsetf ( std::ios::showbase ); // deactivate showbase
std::cout << 100 << '\n';
return 0;
}輸出:
0x64
64
4. 讀取/設置顯示浮點數時的精度
[cpp]
streamsize precision() const;
streamsize precision (streamsize prec);
streamsize precision() const;
streamsize precision (streamsize prec); 例子:
[cpp]
// modify precision
#include <iostream> // std::cout, std::ios
int main () {
double f = 3.14159;
std::cout.unsetf ( std::ios::floatfield ); // floatfield not set
std::cout.precision(5);
std::cout << f << '\n';
std::cout.precision(10);
std::cout << f << '\n';
std::cout.setf( std::ios::fixed, std:: ios::floatfield ); // floatfield set to fixed
std::cout << f << '\n';
return 0;
}
// modify precision
#include <iostream> // std::cout, std::ios
int main () {
double f = 3.14159;
std::cout.unsetf ( std::ios::floatfield ); // floatfield not set
std::cout.precision(5);
std::cout << f << '\n';
std::cout.precision(10);
std::cout << f << '\n';
std::cout.setf( std::ios::fixed, std:: ios::floatfield ); // floatfield set to fixed
std::cout << f << '\n';
return 0;
}輸出:
3.1416
3.14159
3.1415900000
5. 讀取/設定流的輸出數據的顯示寬度
[cpp]
streamsize width() const;
streamsize width (streamsize wide);
streamsize width() const;
streamsize width (streamsize wide); 例子:
[cpp]
// field width
#include <iostream> // std::cout, std::left
int main () {
std::cout << 100 << '\n';
std::cout.width(10);
std::cout << 100 << '\n';
std::cout.fill('x');
std::cout.width(15);
std::cout << std::left << 100 << '\n';
return 0;
}
// field width
#include <iostream> // std::cout, std::left
int main () {
std::cout << 100 << '\n';
std::cout.width(10);
std::cout << 100 << '\n';
std::cout.fill('x');
std::cout.width(15);
std::cout << std::left << 100 << '\n';
return 0;
}輸出:
100
100
100xxxxxxxxxxxx
語言環境:
1. 給流設置本地語言環境
[cpp]
locale imbue (const locale& loc);
locale imbue (const locale& loc); 例子:
[cpp]
// imbue example
#include <iostream> // std::cout
#include <locale> // std::locale
int main()
{
std::locale mylocale(""); // get global locale
std::cout.imbue(mylocale); // imbue global locale
std::cout << 3.14159 << '\n';
return 0;
}
// imbue example
#include <iostream> // std::cout
#include <locale> // std::locale
int main()
{
std::locale mylocale(""); // get global locale
std::cout.imbue(mylocale); // imbue global locale
std::cout << 3.14159 << '\n';
return 0;
}輸出:
3,14159
2. 獲取當前使用語言環境
[cpp] locale getloc() const;
locale getloc() const;
1.2 basic_ios
basic_ios定義出“與字符類型及其相應字符特性相關”的stream class的共同屬性,其中包括清除流狀態、設置流狀態、拷貝流標志、返回或設置流緩沖區指針、設置本地化相關信息、返回或設置填充字符、字符轉換,還包括了stream所用的緩沖器.
basic_ios在其內部定義了一個指向streambuf的指針。
[cpp] template <class Elem, class Traits>
class basic_ios
: public ios_base
{
//C++標准庫封裝了一個緩沖區類streambuf,以供輸入輸出流對象使用。
//每個標准C++輸出輸出流對象都包含一個指向streambuf的指針,
basic_streambuf<_Elem, _Traits>*_Mystrbuf;
// ....
}
template <class Elem, class Traits>
class basic_ios
: public ios_base
{
//C++標准庫封裝了一個緩沖區類streambuf,以供輸入輸出流對象使用。
//每個標准C++輸出輸出流對象都包含一個指向streambuf的指針,
basic_streambuf<_Elem, _Traits>*_Mystrbuf;
// ....
}