Чтение сжатых файлов с использованием STL-вектора указателей на igzstreams - PullRequest
0 голосов
/ 25 октября 2011

В качестве ввода у меня есть список сжатых файлов.Как показано здесь , я использую gzstream для их обработки.Из практических соображений я хочу открыть каждый файл и записать каждый поток в вектор.Это кажется довольно простым, но мне не удается заставить его работать.Вот минимальный код:

#include <cstdlib>

#include <iostream>
#include <vector>
using namespace std;

#include <gzstream.h>

int main (int argc, char ** argv)
{
  size_t i;
  vector<string> vInFiles;
  vector<igzstream *> vStreams;
  string line;

  // create the dummy input files
  system ("rm -f infile*.gz; for i in {1..2}; do echo \"toto\"${i} | gzip > infile${i}.gz; done");
  vInFiles.push_back ("infile1.gz");
  vInFiles.push_back ("infile2.gz");

  // open each input file
  for (i = 0; i < vInFiles.size(); ++i)
  {
    igzstream inStream;
    inStream.open (vInFiles[i].c_str());
    if (! inStream.good())
    {
      cerr << "ERROR: can't open file " << vInFiles[i] << endl;
      exit (1);
    }
    vStreams.push_back (&inStream);
  }

  // manipulate each input file
  for (i = 0; i < vInFiles.size(); ++i)
  {
    cout << "read first line of file " << vInFiles[i] << endl;
    getline (*(vStreams[i]), line);
    if (line.empty())
    {
      cerr << "empty line" << endl;
      exit (1);
    }
    cout << line << endl;
  }

  // close each input file
  for (i = 0; i < vInFiles.size(); ++i)
  {
    vStreams[i]->close();
  }
  vStreams.clear();

  return 0;
}

Этот код правильно компилируется:

$ gcc -Wall test.cpp -lstdc++ -lgzstream -lz

И хотя он работает нормально, он не читает файлы должным образом:

$ ./a.out
read first line of file infile1.gz
empty line                

Ответы [ 3 ]

2 голосов
/ 25 октября 2011

Ваши указатели потока недействительны после окончания итерации, так как объект автоматического потока уничтожается. Если вам это действительно нужно, вам нужно разместить их в бесплатном магазине (или сделать igzstream движимым).

// std::vector<boost::shared_ptr<igzstream>> for C++03 
std::vector<std::unique_ptr<igzstream>> vStreams;

// ...

for (size_t i = 0; i < vInFiles.size(); ++i) {
    // boost::shared_ptr<igzstream> inStream = boost::make_shared<igzstream>();
    auto inStream = std::unique_ptr<igzstream>(new igzstream);
    inStream->open(...);
    // ...
    vStreams.push_back(inStream);
}

// ...
0 голосов
/ 25 октября 2011

Как уже упоминалось в комментариях, я бы предпочел не использовать Boost, и у меня есть только gcc 4.1.2. Таким образом, вот решение, использующее бесплатный магазин , благодаря предложению Cat Plus Plus:

  // open each input file
  for (i = 0; i < vInFiles.size(); ++i)
  {
    igzstream * pt_inStream = new igzstream;
    pt_inStream->open (vInFiles[i].c_str());
    if (! pt_inStream->good())
    {
      cerr << "ERROR: can't open file " << vInFiles[i] << endl;
      exit (1);
    }
    vStreams.push_back (pt_inStream);
  }

И

  // close each input file                                                                                                                                                                                                                                           
  for (i = 0; i < vInFiles.size(); ++i)
  {
    vStreams[i]->close();
    delete vStreams[i];
  }
0 голосов
/ 25 октября 2011

Это сломано; Вы сохраняете вектор указателей на потоки, но инициализируете его указателем на локальный автоматический экземпляр потока (внутри цикла for). Как только каждая итерация цикла завершается, этот экземпляр выходит из области видимости, и у вас есть указатель на какую-то ерунду.

Затем вы используете это дерьмо позже, и вы получаете дерьмо.

Используйте умный указатель, например,

  std::vector<boost::shared_ptr<igzstream> > vStreams;
  // to initialize
  for (i = 0; i < vInFiles.size(); ++i)
  {
    boost::shared_ptr<igzstream> inStream(new igzstream(vInFiles[i].c_str());
    if (!inStream->good())
    {
      cerr << "ERROR: can't open file " << vInFiles[i] << endl;
      exit (1);
    }
    vStreams.push_back (inStream); // save the smart pointer
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...