Може ли boost iostreams да чете и компресира gzipped файлове в движение?

Чета gzipped файл, използвайки boost iostreams: Следното работи добре:

 namespace io = boost::iostreams;
  io::filtering_istream in;
  in.push(boost::iostreams::basic_gzip_decompressor<>());
  in.push(io::file_source("test.gz"));
  stringstream ss;
  copy(in, ss);

Въпреки това, не искам да приема удара на паметта да прочета цял gzipped файл в паметта. Искам да мога да чета файла постепенно.

Например, ако имам структура от данни X, която се инициализира от istream,

X x;
x.read(in);

не успява. Вероятно това е така, защото може да се наложи да върнем знаци в потока, ако правим частични потоци. Някакви идеи дали boost iostreams поддържа това?


person ATemp    schedule 28.02.2012    source източник
comment
Ще ви свърши ли работа извършването на операция като извикване на getline() след това compressing() чрез цикъл?   -  person user99545    schedule 29.02.2012
comment
@user99545: Не: защото X се създава от двоични данни.   -  person ATemp    schedule 29.02.2012
comment
Не виждам защо не. Използвал съм boost iostreams за четене и писане на zlib-компресирани потоци по този начин.   -  person Ferruccio    schedule 29.02.2012
comment
Това отговаря ли на въпроса? stackoverflow.com/questions/14688296/   -  person Avneesh    schedule 17.01.2014


Отговори (2)


Според документацията на iostream типът boost::io::filtering_istream произлиза от std::istream. Тоест трябва да е възможно това да се предава навсякъде, където се очаква std::istream&. Ако имате грешки по време на изпълнение, защото трябва да unget() или putback() символа, трябва да погледнете параметъра pback_size, който указва колко знака се връщат най-много. Не съм видял в документацията каква е стойността по подразбиране за този параметър.

Ако това не реши проблема ви, можете ли да опишете какъв точно е проблемът ви? От външния вид трябва да работи.

person Dietmar Kühl    schedule 28.02.2012

Мисля, че трябва да напишете свой собствен филтър. Например, за да прочета .tar.gz и да изведа съдържащите се файлове, написах нещо подобно

//using namespace std;
namespace io = boost::iostreams;

struct tar_expander
{
    tar_expander() : out(0), status(header)
    {
    }
    ~tar_expander()
    {
        delete out;
    }

    /* qualify filter */
    typedef char char_type;
    struct category :
        io::input_filter_tag,
        io::multichar_tag
    { };

    template<typename Source>
    void fetch_n(Source& src, std::streamsize n = block_size)
    {
           /* my utility */
           ....
    }

    // Read up to n filtered characters into the buffer s,
    // returning the number of characters read or -1 for EOF.
    // Use src to access the unfiltered character sequence
    template<typename Source>
    std::streamsize read(Source& src, char* s, std::streamsize n)
    {
      fetch_n(src);
      const tar_header &h = cast_buf<tar_header>();
      int r;

      if (status == header)
      {
          ...
      }
      std::ofstream *out;
      size_t fsize, stored;

      static const size_t block_size = 512;
      std::vector<char> buf;

      enum { header, store_file, archive_end } status;
   }
}

Моята функция read(Source &...) при извикване получава разархивирания текст. За да използвате филтъра:

ifstream file("/home/..../resample-1.8.1.tar.gz", ios_base::in | ios_base::binary);
io::filtering_streambuf<io::input> in;
in.push(tar_expander());
in.push(io::gzip_decompressor());
in.push(file);
io::copy(in, cout);
person CapelliC    schedule 28.02.2012