2011-06-10 190 views
1

我想在讀取多個文件之間進行切換。以下是我的代碼的簡化版本。讀取多個文件

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; 
} 

現在它就像魅力,我可以循環,就像我想:-)。我很感謝你的評論,很高興認識大哥還有幫助。

+1

時都處於EOF會發生什麼? – littleadv 2011-06-10 08:34:38

+1

不應該在分配InFile後檢查InFile-> eof()嗎? – 2011-06-10 08:43:31

+0

'如果被稱爲「循環部分」的部分在循環內......例如? – 2011-06-10 08:46:16

回答

4

讓我們看看:您發佈的代碼工作正常,並且您希望我們告訴您 您未發佈的代碼有什麼問題。這相當困難。

不過,您發佈的代碼可能無法正常工作。 std::istream::eof只能在輸入(或某些其他操作)失敗後才能可靠地使用;在你發佈的代碼中,無論如何,幾乎 肯定是錯誤的。

另外:不需要動態分配ifstream;在 事實上,幾乎沒有什麼情況下ifstream 的動態分配是適當的。而且你不檢查打開是否成功。

如果您想一個接一個讀取兩個文件,最簡單的方法是使用兩個循環,一個接一個(調用處理數據的 的通用函數)。如果由於某種原因不合適,我會 使用自定義流緩衝區,它會在構造函數 中獲取文件名列表,並在其到達文件結尾 之前前進到下一個文件,當它到達時僅返回EOF所有 文件的結尾。 (唯一的問題是如果其中一個 open s失敗,我會這麼做,我經常這樣做,它是我的工具包的一部分, ,我使用回調來處理失敗。但是,對於一次性使用, 你可以硬編碼在任何合適)

作爲一個簡單的例子:

// 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

@James Kanze:+1。你的答案提供了一個比我的想法更適合OP代碼中的邏輯的更好方法。 – 2011-06-10 09:03:18

+0

+1。我喜歡這個主意。 – Nawaz 2011-06-10 09:12:35

+0

您的答案投票。然而,作爲一個新手,我對理解代碼有困難,並且需要更多時間來研究它。不過,我有幾個問題。 1.這些文件有可能被多次使用嗎?你能否在代碼中加入一些評論,以幫助我理解。我很感激。 – Deadie 2011-06-10 09:17:00

0
#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; 
}