Может ли iostreams повысить скорость чтения и сжатия сжатых файлов на лету? - PullRequest
6 голосов
/ 28 февраля 2012

Я читаю сжатый файл, используя 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);

Однако я не хочу воспринимать попадание в память чтения всего сжатого файла в память.Я хочу, чтобы можно было читать файл постепенно.

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

X x;
x.read(in);

завершится неудачно.Предположительно, это потому, что нам, возможно, придется возвращать символы в поток, если мы делаем частичные потоки.Есть идеи, поддерживает ли boost iostreams это?

Ответы [ 2 ]

1 голос
/ 29 февраля 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);
1 голос
/ 29 февраля 2012

Согласно документации iostream тип boost::io::filtering_istream происходит от std::istream. То есть это должно быть возможно передать везде, где ожидается std::istream&. Если у вас есть ошибки во время выполнения, потому что вам нужно unget() или putback() символов, вы должны взглянуть на параметр pback_size, который указывает, какое количество символов возвращается максимум. Я не видел в документации значения этого параметра по умолчанию.

Если это не решит вашу проблему, можете ли вы описать, в чем именно заключается ваша проблема? Судя по всему это должно работать.

...