繁体   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