Чтение нескольких файлов - PullRequest
1 голос
/ 10 июня 2011

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

ifstream* In_file1 = new ifstream("a.dat",  ios::binary);
ifstream* In_file2 = new ifstream("b..dat",  ios::binary);
ifstream* In_file;
int ID;

In_file = In_file1; 
int ID = 0;

//LOOPING PORTION
if (In_file -> eof())
{
  In_file -> seekg(0, ios_base::beg);
  In_file->close();

  switch (ID)
   {
     case 0:
           In_file = In_file2;  ID = 1; break;
     case 1:
          In_file = In_file1; ID = 0;  break;
   }
}
//some codes
:
:
In_file->read (data, sizeof(double));

//LOOPING PORTION

Код работает хорошо, если я читаю файлы один раз и думал, что все круто. Однако, если часть, называемая «часть цикла», находится внутри цикла, то поведение становится странным, и я начинаю иметь один повторяющийся вывод. Пожалуйста, может кто-нибудь сказать мне, что не так и как я могу это исправить? Если у вас есть лучший способ решения проблемы, пожалуйста, предложите. Я ценю его.

// решаемые

Спасибо всем за ваши комментарии, я ценю это. Вот что я сделал просто:

Вместо оригинала

switch (ID)
{
  case 0:
   In_file = In_file2;  ID = 1; break;
   case 1:
   In_file = In_file1; ID = 0;  break;
}

Я просто сделал

switch (ID)
{
  case 0:
   In_file = new ifstream("a.dat",  ios::binary);  ID = 1; break;
  case 1:
  In_file = new ifstream("b.dat",  ios::binary);  ID = 0;  break;
}

Теперь это работает как шарм, и я могу зацикливаться столько, сколько хочу :-). Я ценю ваши комментарии, приятно знать, что старший брат все еще помогает.

Ответы [ 2 ]

4 голосов
/ 10 июня 2011

Давайте посмотрим: код, который вы опубликовали, работает нормально, и вы хотите, чтобы мы сказали вам, что не так с кодом, который вы не опубликовали.Это довольно сложно.

Тем не менее, код, который вы разместили, вероятно, не будет работать правильно.std::istream::eof может надежно использоваться только после сбоя входа (или какой-либо другой операции);в опубликованном вами коде он почти наверняка будет ложным, независимо от того.

Кроме того: нет необходимости динамически выделять ifstream;фактически практически нет случаев, когда динамическое распределение ifstream является подходящим.И вы не проверяете, что открытия были успешными.

Если вы хотите прочитать два файла, один за другим, самый простой способ - использовать два цикла, один за другим (вызывая общую функцию дляобработка данных).Если по какой-то причине это не подходит, я бы использовал пользовательский streambuf, который принимает список имен файлов в конструкторе и переходит к следующему, когда достигает одного конца файла, возвращая EOF только когда он достигконец всех файлов.(Единственное осложнение в этом состоит в том, что делать в случае сбоя одного из open. Я делаю это достаточно часто, чтобы он был частью моего набора инструментов, и использую функцию обратного вызова для обработки сбоя.Вы можете просто жестко написать код в любом удобном для вас месте.)

В качестве быстрого примера:

//  We define our own streambuf, deriving from std::streambuf
//  (All istream and ostream delegate to a streambuf for the
//  actual data transfer; we'll use an instance of this to
//  initialize the istream we're going to read from.)
class MultiFileInputStreambuf : public std::streambuf
{
    //  The list of files we will process
    std::vector<std::string> m_filenames;
    //  And our current position in the list (actually
    //  one past the current position, since we increment
    //  it when we open the file).
    std::vector<std::string>::const_iterator m_current;

    //  Rather than create a new filebuf for each file, we'll
    //  reuse this one, closing any previously open file, and
    //  opening a new file, as needed.
    std::filebuf m_streambuf;

protected:
    //  This is part of the protocol for streambuf.  The base
    //  class will call this function anytime it needs to
    //  get a character, and there aren't any in the buffer.
    //  This function can set up a buffer, if it wants, but
    //  in this case, the buffering is handled by the filebuf,
    //  so it's likely not worth the bother.  (But this depends
    //  on the cost of virtual functions---without a buffer,
    //  each character read will require a virtual function call
    //  to get here.
    //
    //  The protocol is to return the next character, or EOF if
    //  there isn't one.
    virtual int underflow()
    {
        //  Get one character from the current streambuf.
        int result = m_streambuf.sgetc();
        //  As long as 1) the current streambuf is at end of file,
        //  and 2) there are more files to read, open the next file
        //  and try to get a character from it.
        while ( result == EOF && m_current != m_filenames.eof() ) {
            m_streambuf.close();
            m_streambuf.open( m_current->c_str(), std::ios::in );
            if ( !m_streambuf.is_open() )
                //  Error handling here...
            ++ m_current;
            result = m_streambuf.sgetc();
        }
        //  We've either gotten a character from the (now) current
        //  streambuf, or there are no more files, and we'll return
        //  the EOF from our last attempt at reading.
        return result;
    }

public:
    //  Use a template and two iterators to initialize the list
    //  of files from any STL sequence whose elements can be
    //  implicitly converted to std::string.
    template<typename ForwardIterator>
    MultiFileInputStreambuf(ForwardIterator begin, ForwardIterator end)
        : m_filenames(begin, end)
        , m_current(m_filenames.begin())
    {
    }
};
0 голосов
/ 28 апреля 2013
#include <iostream>
#include <fstream>
#include <string>

#define NO_OF_FILES 2

int main () 
{
  std::ifstream in;
  std::string line;
  std::string files[NO_OF_FILES] = 
  {
    "file1.txt", 
    "file2.txt",
  };
  // start our engine!
  for (int i = 0; i < NO_OF_FILES; i++)
  {
    in.open(files[i].c_str(), std::fstream::in);
    if (in.is_open())
    {
      std::cout << "reading... " << files[i] << endl;
      while (in.good())
      {
        getline(in, line);
        std::cout << line << std::endl;
      }
      in.close();
      std::cout << "SUCCESS" << std::endl;
    }
    else
      std::cout << "Error: unable to open " + files[i] << std::endl;
  }

  return 0;
}
...