【问题标题】:Seek doesn't work on std::istream initialized with boost filtering_istreambufSeek 在使用 boost filtering_istreambuf 初始化的 std::istream 上不起作用
【发布时间】:2015-12-22 11:37:39
【问题描述】:

我正在尝试读取文件。它应该是内存映射以提高性能。我想使用 iostreams 的 boost 过滤器链来轻松包含 zip、bzip2 和 gzip 解压缩。

我尝试采用Using boost::iostreams mapped_file_source and filtering_streambuf to decompress file提出的解决方案。

我的问题:当我尝试在流上seek() 时,我得到一个异常:“没有随机访问”。这很奇怪,因为从文档中我了解到我可以使用std::istream 作为接口。

我想出了以下代码 (also on coliru):

#include <iostream>
#include <stdio.h>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>

// and later also include ...
//#include <boost/iostreams/filter/gzip.hpp>
//#include <boost/iostreams/filter/bzip2.hpp>

int main()
{
    namespace io = boost::iostreams;
    io::mapped_file_source inputDevice;                           // the device to read from (file)
    io::stream<io::mapped_file_source> mappedFileStream; // the memory mapped file stream    
    io::filtering_istreambuf filteredInputStream;                 // the source file (stream), together with a chain of filters and/or decompressors


    inputDevice = io::mapped_file_source("main.cpp");
    mappedFileStream.open(inputDevice);      // open device as a readable stream
    // add optional filter/decoder/decompressor
    //filteredInputStream.push(io::bzip2_decompressor());
    //filteredInputStream.push(io::zlib_decompressor());
    //filteredInputStream.push(io::gzip_decompressor());
    //filteredInputStream.push(io::base64_decoder());
    filteredInputStream.push(mappedFileStream);  //finally add the readable stream 
    // now we have a device that is streamed and the contents are filtered the resulting stream can be used like a std::iostream. (in theory)
    std::istream inputStream(&filteredInputStream);

    std::cout << inputStream.get() << std::endl;
    std::cout << inputStream.get() << std::endl;
    //fatal error: class boost::exception_detail::clone_impl<struct boost::exception_detail::error_info_injector<class std::ios_base::failure> >: no random access
    filteredInputStream.pubseekoff(0, std::ios_base::beg, std::ios_base::in | std::ios_base::out);
    inputStream.seekg(0);  // fatal error: class boost::exception_detail::clone_impl<struct boost::exception_detail::error_info_injector<class std::ios_base::failure> >: no random access
    std::cout << inputStream.get() << std::endl;
    std::cout << inputStream.get() << std::endl;
    return 0;
}

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    在撰写问题时,我在这里找到了解决方案。

    boost::iostreams, gzip files and tellg

    问题与 gzip 有关,但 boost iostream 缓冲区似乎默认为不可搜索。我误解了 boost 文档。

    所以这里是解决方案:

    替换:

    io::filtering_istreambuf filteredInputStream;         
    

    io::filtering_streambuf<io::input_seekable> filteredInputStream;  
    

    在 coliru 上直播:http://coliru.stacked-crooked.com/a/aff637be181a27da

    #include <iostream>
    #include <stdio.h>
    #include <boost/iostreams/device/mapped_file.hpp>
    #include <boost/iostreams/stream.hpp>
    #include <boost/iostreams/filtering_streambuf.hpp>
    
    
    // and later also include ...
    //#include <boost/iostreams/filter/gzip.hpp>
    //#include <boost/iostreams/filter/bzip2.hpp>
    
    int main()
    {
        namespace io = boost::iostreams;
        io::mapped_file_source inputDevice;                               // the device to read from (file)
        io::stream<io::mapped_file_source> mappedFileStream;              // the memory mapped file stream    
        io::filtering_streambuf<io::input_seekable> filteredInputStream;  // the source file (stream), together with a chain of filters and/or decompressors
        //io::filtering_istreambuf filteredInputStream;                   // wrong. Defaults to non-seekable. Throws exception on seek or tell
    
    
        inputDevice = io::mapped_file_source("main.cpp");
        mappedFileStream.open(inputDevice);      // open device as a readable stream
        // add optional filter/decoder/decompressor
        //filteredInputStream.push(io::bzip2_decompressor());
        //filteredInputStream.push(io::zlib_decompressor());
        //filteredInputStream.push(io::gzip_decompressor());
        //filteredInputStream.push(io::base64_decoder());
        filteredInputStream.push(mappedFileStream);  //finally add the readable stream 
        // now we have a device that is streamed and the contents are filtered the resulting stream can be used like a std::iostream. (in theory)
        std::istream inputStream(&filteredInputStream);
    
        std::cout << inputStream.get() << std::endl;
        std::cout << inputStream.get() << std::endl;
        filteredInputStream.pubseekoff(0, std::ios_base::beg, std::ios_base::in | std::ios_base::out);
        inputStream.seekg(0);  
        std::cout << inputStream.get() << std::endl;
        std::cout << inputStream.get() << std::endl;
        return 0;
    }
    

    【讨论】:

    猜你喜欢
    • 2015-09-14
    • 2018-01-13
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    相关资源
    最近更新 更多