6

关于 boost filtering_streams 的一些基本问题。我有几十个函数采用 std::ofstream& 参数

void foo(std::ofstream& outStream)
{
    // lots of operations, like this:
    outStream << "various bits of text";
}

void StreamSomeTextToFile(char* fileName)
{
    ofstream myFileStream(fileName, ios::out | ios::app | ios::binary);
    foo(myFileStream);
    myFileStream.close();
}

现在我想使用 boost filtering_stream 输出到一个压缩的 ZIP 文件。用于打包和解包的常用 boost filtering_streams 测试代码已编译、链接并完美地为我工作。我想替换过滤流:

void StreamSomeCompressedTextToFile(char* fileName)
{
    ofstream myFileStream(destPath, std::ios_base::out | std::ios_base::app | std::ios_base::binary);
    boost::iostreams::filtering_streambuf<boost::iostreams::output> myCompressedFileStream;
    myCompressedFileStream.push(boost::iostreams::zlib_compressor());
    myCompressedFileStream.push(myFileStream);

    foo(myCompressedFileStream);    // I can't just pass myCompressedFileStream to foo(std::ofstream&), right?
    myFileStream.close();
}

三个问题:

1) 我以前接受 std::ofstream& outStream 的所有函数现在是否需要接受 boost::iostreams::filtering_streambuf& 类型的参数?或者是否有适当的参数类型,以便那些众多(“foo”)函数可以与任何一种类型的流类型一起使用?

2) 在我的简单测试用例中,我无法将流运算符语法与过滤流缓冲区一起使用:

myCompressedFileStream << "some text";

这产生了错误:'operator<<'不匹配。我同样用 write() 编译错误:

error: 'class boost::iostreams::filtering_streambuf<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char>, boost::iostreams::public_>' has no member named 'write'

3)在常见的测试用例示例代码(如下)中,我很困惑在创建文件“hello.z”后找不到它。解包代码(也在下面)清楚地引用了它——那么在哪里可以找到它呢?注意:这个位置终于被发现了:它在 /Library/Preferences/

void pack()
{            
    std::ofstream file("hello.z", std::ios_base::out | std::ios_base::binary);

    boost::iostreams::filtering_streambuf<boost::iostreams::output> out;
    out.push(boost::iostreams::zlib_compressor());
    out.push(file);       
    char data[5] = {'a', 'b', 'c', 'd', 'e'};    
    boost::iostreams::copy(boost::iostreams::basic_array_source<char>(data, sizeof(data)), out);
    file.close();
}

void unpack()
{
    std::fstream file("hello.z", std::ios_base::in | std::ios_base::binary);
    boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
    in.push(boost::iostreams::zlib_decompressor());
    in.push(file);
    boost::iostreams::copy(in, std::cout);
}

顺便说一句:XCode 3.2.6、GNU 4.0、OS X 10.6.8

4

2 回答 2

3

按顺序回答问题:

1:流缓冲区对象(如 boost::iostream::filtering_streambuf 或 std::streambuf)不能与流对象(如 std::ostream 或 boost 的实现)互换。话虽如此,您可以将诸如“myCompressedFileStream”之类的流缓冲区对象传递给 ostream 对象的构造函数(此 boost iostream 教程提供了一个不错的示例解释)。而且因为 boost 的 streambufs 与标准库中的那些兼容,所以您不需要更改任何接受 std::ostream/ofstream 引用的函数。您只是不能将流缓冲区作为流传递。

2:同上,插入操作符是为流定义的,而不是流缓冲区。

3:通常在可执行文件的目录中创建不带目录名的文件。话虽如此,我有时发现 Finder 反映由非 Finder 进程更新/创建的文件有点慢。我没有在终端中使用 ls 遇到这些问题。不过,不知道这是否与您的问题有关。

于 2013-07-25T07:23:54.193 回答
2

成功!

Paul Schellin(上图)和一些关于 Boost 用户的提示组合得出了答案:

1) Boost 用户 Frédéric 指出“在 output_file [filtering_ostream] 被破坏之前什么都不会发生。所以请包含在 { } 中”。这是必不可少的缺失部分,因为在我的过滤流缓冲区被破坏之前,我试图在我的 ofstream 上执行 file.close()。这就解释了为什么文件是空的!

重新阅读文档发现:

  "By default, if the Device at the end of the chain is popped
   or if the filtering_stream is complete when it is destroyed,
   all the filters and devices in the chain are closed using the
   function close. This behavior can be modified using the member
   function set_auto_close"

这种状态是不需要将compressor() 或ofstream (file) 从filtering_stream 的堆栈中“弹出”,也不需要调用close()。只需破坏 filtering_stream 对象,所有内容都会被写出并清理。一个晦涩的细节,一个与人们所期望的背道而驰的细节。

3) Boost 用户 Holger Gerth 质问我为什么要使用 filter_streambuf,而我本来可以使用 filter_stream。事实是,我不确定,但是,在我的实验中,我既不能从 filter_stream 构造 ostream(我需要将其传递给其他函数),也不能通过 filter_stream 来代替我需要的 ostream。

即使在阅读了有关filtering_streambuf 与filtering_stream 的几篇文章之后,我仍然对如何以及为什么(出于我的目的)我会使用filtering_stream 而不是从filtering_streambuf 构造一个ostream 感到困惑。

所以,回顾一下:

1) 从filtering_streambuf 构造一个单独的ostream,并将其传递给foo() 或Stream Insertion 运算符(即<<)。

2) 不要调用 myFileStream.close();

于 2013-07-27T02:39:09.463 回答