Overview
Features
Download
Documentation
Community
Add-Ons & Services

UnbufferedStreamBuf and ZipArchive

Please post support and help requests here.

UnbufferedStreamBuf and ZipArchive

Postby blumf » 28 Jan 2014, 18:26

I've been trying out passing an UnbufferedStreamBuf to a ZipArchive but it doesn't seem to read it all.

Using a simple no-op UnbufferedStreamBuf class...

Code: Select all
class MyStreamBuf : public Poco::UnbufferedStreamBuf
{
public:
   MyStreamBuf(std::istream& istr)
      : _istr(istr)
   { }

protected:
   int readFromDevice()
   {
      int c = _istr.get();
      return c;
   }

private:
   std::istream& _istr;
};

class MyIOS : public virtual std::ios
{
public:
   MyIOS(std::istream& istr)
      : _buf(istr)
   {
      poco_ios_init(&_buf);
   }

protected:
   MyStreamBuf _buf;
};

class MyInputStream: public MyIOS, public std::istream
{
public:
   MyInputStream(std::istream& istr)
      : MyIOS(istr)
      , std::istream(&_buf)
   { }
};


The following works fine and the output.zip file can be read by ZipArchive (and any other zip util) as normal

Code: Select all
std::ifstream in_file("input.zip", std::ifstream::in | std::ifstream::binary);
MyInputStream my_strm(in_file);

std::ofstream out_file("output.zip", std::ifstream::out | std::ifstream::binary);

Poco::StreamCopier::copyStream(my_strm, out_file);


But I can't do

Code: Select all
std::ifstream in_file("input.zip", std::ifstream::in | std::ifstream::binary);
MyInputStream my_strm(in_file);

ZipArchive arc(my_strm);

auto iter = arc.headerBegin();
while(iter != arc.headerEnd()) {
   std::cout << iter->first << std::endl;
   ++iter;
}


It just lists the first directory in the zip and finishes.

I suspect I might be doing something wrong in readFromDevice function, or do I need to use the buffered stream classes?
blumf
 
Posts: 2
Joined: 28 Jan 2014, 18:01

Re: UnbufferedStreamBuf and ZipArchive

Postby blumf » 29 Jan 2014, 19:07

For the time being, I've found a way using boost iostreams...

Code: Select all
#include <boost/iostreams/filtering_stream.hpp>
namespace io = boost::iostreams;

struct my_filter : public io::filter<io::input_seekable> {
   template<typename Source>
   int get(Source& src)
   {
      int c = io::get(src);

      return c;
   }

   template<typename Source>
   std::streampos seek(Source& d, io::stream_offset off, std::ios_base::seekdir way)
   {
      return io::seek(d, off, way);
   }
};

// ... in func ...
   std::ifstream in_file("input.zip", std::ifstream::in | std::ifstream::binary);

   io::filtering_stream<io::input_seekable> in;
   in.push(my_filter());
   in.push(in_file);

   ZipArchive arc(in);

   auto iter = arc.headerBegin();
   while(iter != arc.headerEnd()) {
      std::cout << iter->first << std::endl;
      ++iter;
   }


Which seems to work.
blumf
 
Posts: 2
Joined: 28 Jan 2014, 18:01


Return to Support

Who is online

Users browsing this forum: No registered users and 3 guests