【问题标题】:Creating a std::iostream adapter创建 std::iostream 适配器
【发布时间】:2012-07-14 15:17:09
【问题描述】:

我想创建一个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 子类中,但这似乎相当复杂。

有没有更简单的方法可以做到这一点?

【问题讨论】:

  • 看来你应该学习流操纵器的概念。搜索它,这里有一个例子stackoverflow.com/questions/799599/…或这里stackoverflow.com/questions/535444/…
  • 您看过boost iostreams 库吗?这已经有了压缩过滤器(虽然没有 lzma AFAIK)和使编写自定义过滤器更简单的机制。
  • 正确的做法是写一个自定义的streambuf。这确实不是一项复杂的任务。真正唯一的困难是找到描述需要做什么的参考资料。

标签: c++ iostream std


【解决方案1】:

奇怪的是,至少在事情确实打算工作的情况下,这些都不应该直接涉及 iostream 和/或 streambuf。

我认为 iostream 是一个媒人类。 iostream 有一个 streambuf,它为某种外部数据源/接收器提供缓冲接口。它还具有处理所有格式的语言环境。 iostream 只不过是让这两个人一起玩得很好的操场监督员(可以这么说)。由于您正在处理数据格式,所有这些都(或应该)在语言环境中处理。

虽然语言环境不是单一的——它由许多facets 组成,每个@s 专门用于数据格式化的一个特定部分。在这种情况下,您可能关心的部分是codecvt facet,它用于(几乎完全)在从 iostream 读取/写入 iostream 的数据的外部和内部表示之间进行转换。

然而,无论好坏,一个语言环境一次只能包含 一个 codecvt facet,而不是像您正在考虑的那样包含它们的链。因此,您真正需要/想要的是一个包装类,它提供一个 codecvt 作为其外部接口,但允许您在 I/O 期间链接一些任意的数据转换集。

对于utf到utf的转换,Boost.locale提供了utf_to_utf函数,以及codecvt封装代码,所以这部分的转换简单直接。

为了避免有人建议使用 ICU 来完成这些事情,我将补充一点,Boost.Locale 几乎是 ICU 的一个包装器,所以这或多或少是相同的答案,但其形式对 C++ 更友好(而 ICU 本身就很像 Java,而且几乎完全敌视 C++)。

另一方面,编写 codecvt facet 为一项相当简单的任务增加了很多复杂性。过滤流缓冲区(例如)通常很多更容易编写。它仍然没有你想的那么简单,但也没有 codecvt 方面那么糟糕。正如@Flexo 已经提到的,Boost iostreams 库已经包含一个过滤流缓冲区,它可以进行 zip 压缩。对 lzma(或 lzh、算术等压缩)进行大致相同的操作相对容易,至少假设您具有易于使用的压缩功能(您基本上只是为它们提供输入缓冲区,并且它们提供的缓冲区为结果)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多