簡體   English   中英

創建std :: iostream適配器

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM