[英]Creating a std::iostream adapter
我想創建一個iostream
適配器類,它允許我在運行中修改寫入或讀取流的數據。 適配器本身應該是一個iostream
以實現對第三方代碼的真正透明。
從std::ostream
派生的StreamEncoder
類的示例:
// External algorithm, creates large amounts of log data
int foo(int bar, std::ostream& logOutput);
int main()
{
// The target file
std::ofstream file("logfile.lzma");
// A StreamEncoder compressing the output via LZMA
StreamEncoder lzmaEncoder(file, &encodeLzma);
// A StreamEncoder converting the UTF-8 log data to UTF-16
StreamEncoder utf16Encoder(lzmaEncoder, &utf8ToUtf16);
// Call foo(), but write the log data to an LZMA-compressed UTF-16 file
cout << foo(42, utf16Encoder);
}
據我所知,我需要創建一個新的basic_streambuf
派生並將其嵌入basic_ostream
子類中,但這似乎相當復雜。
有沒有更簡單的方法來實現這一目標?
奇怪的是,至少在事情確實有效的情況下,這些都不應該直接涉及到iostreams和/或streambufs。
我會把iostream想象成一個匹配者類。 iostream有一個streambuf,它為某種外部數據源/接收器提供緩沖接口。 它還有一個區域設置,可以處理所有格式。 iostream不僅僅是游樂場的主管,讓這兩個人在一起玩得很好(可以這么說)。 由於您正在處理數據格式化,因此所有這些都是(或應該)在語言環境中處理。
雖然語言環境不是單一的 - 它由許多facet
組成,每個facet
都專門用於數據格式化的一個特定部分。 在這種情況下,您可能關心的部分是codecvt
facet,它(幾乎唯一地)用於在從iostreams讀取/寫入的數據的外部和內部表示之間進行轉換。
然而,無論好壞,一個語言環境一次只能包含一個 codecvt方面,而不是像你正在考慮的那樣。 因此,您真正需要/想要的是一個包裝類,它提供了一個codecvt作為其外部接口,但允許您在I / O期間鏈接一些任意的變換集。
對於utf-to-utf轉換,Boost.locale提供了utf_to_utf函數和codecvt包裝器代碼,因此執行此部分轉換非常簡單明了。
為了避免有人建議用ICU完成這些事情,我會補充說Boost.Locale幾乎是ICU的一個包裝器,所以這或多或少是相同的答案,但是對C ++更友好的形式(而ICU)它本身就像Java一樣,而且幾乎完全不喜歡C ++)。
事情的另一面是編寫一個codecvt方面為一個相當簡單的任務增加了很多復雜性。 過濾streambuf(例如)通常編寫起來要簡單得多。 它仍然不是你想要的那么容易,但並不像codecvt方面那么糟糕。 正如@Flexo已經提到的,Boost iostreams庫已經包含了一個壓縮壓縮的過濾streambuf。 與lzma(或lzh,算術等壓縮)大致相同是相對容易的,至少假設你有易於使用的壓縮函數(你基本上只為它們提供輸入緩沖區,並且它們提供緩沖區結果)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.