2015-12-22 1 views
3

Я пытаюсь прочитать файл. Он должен быть отображен в память для производительности. Я бы хотел использовать цепочку форсированного фильтра для iostreams, чтобы легко включить распаковку zip, bzip2 и gzip.Seek не работает на std :: istream инициализирован с boost filtering_istreambuf

Я попытался принять решение, предложенное в 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; 
} 

ответ

4

При составлении вопроса, я нашел решение здесь.

boost::iostreams, gzip files and tellg

Вопрос связан с Gzip, но увеличить iostream буфер, кажется, по умолчанию, не для перемещения. Я неправильно понял документацию по ускорению.

Так вот решение:

Заменить:

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; 
} 
+0

Вы пытались это с какой-либо из декомпрессоры? В boost 1.61.0 я получаю ошибки утверждения. – Erroneous

Смежные вопросы