2017-06-05 80 views
2

我正在使用std::ifstream::read從管道(Linux)或管道類設備對象(Windows)讀取數據。但是,當沒有更多數據時,read讀取0個字節並設置EOF。有沒有辦法阻止從ifstream讀取數據,這樣只有在有更多數據時纔會返回?阻止讀取std :: ifstream

我寧可不等待EOF標誌清除。

如果C++標準庫不可能,那麼最接近的其他選項是什麼?我可以用普通的C語言來做到這一點,還是我不得不求助於操作系統特定的API?

回答

3

不幸的是,std在任何非算法功能(如IO)上都很差。你總是必須依賴第三方解決方案。幸運的是,有Boost,如果你不介意的話,我會建議使用它來減少操作系統特定的代碼。

namespace bs = boost::iostreams; 
    int fd; // Create, for example, Posix file descriptor and specify necessary flags for it. 
    bs::file_descriptor_source fds(fd); 
    bs::stream<bs::file_descriptor_source> stream(fds); 
    // Work with the stream as it is std stream 

在我使用Boost IO Streams並且具體file_descriptor_source,它作爲一個基礎流裝置和內部隱藏Windows或Posix的特定管這個小的例子。您打開自己的管道,以便您可以根據需要配置管道。

+0

謝謝,我會試試看。不幸的是,在Windows上安裝Boost非常複雜,只需將它全部寫入WinApi中即可開始使用;-)。 – jdm

+0

如果你正在使用MinGW,你可以使用'packman'來根據這個軟件包庫[Alexpux Packages](https://github.com/Alexpux/MINGW-packages)進行安裝。 – Yuki

+1

而對於Visual Studio有[這些二進制文件](https://sourceforge.net/projects/boost/files/boost-binaries/1.64.0/) – Yuki

0

好吧,似乎沒有辦法做一個阻塞閱讀。清除錯誤位不會有幫助。只有重新打開就像這個例子FIFO的:

int main(int argc, char **argv) 
{ 
    int rc=0; 
    enum FATAL {ERR_ARGV,ERR_OPEN_FILE}; 
    try 
    { 
      if(argv[1] == NULL) throw ERR_ARGV; 
      std::ifstream fifo; 

      while(1) 
      { 
        fifo.open(argv[1],std::ifstream::in); 
        if(!fifo.is_open()) throw ERR_OPEN_FILE; 

        std::string line; 
        while(std::getline(fifo,line)) 
        { 
          std::cout << line << "\n"; fflush(stdout); 
        } 
        fifo.close(); 
      } 
      // never should come here 
    } 
    catch(FATAL e) 
    { 
      rc=e; 
      switch(e) 
      { 
      case ERR_ARGV: 
        std::cerr << "ERROR: argument 1 should be a fifo file name\n"; 
        break; 
      case ERR_OPEN_FILE: 
        std::cerr << "ERROR: unabel to open file " << argv[1] << "\n"; 
        break; 
      } 
    } 
    return(rc); 
} 

我已經測試此代碼和它的作品從FIFO做無盡的讀取。

+0

你是什麼意思與「清除錯誤位不會幫助」 ?我可以調用'input.clear()' - 但是之後我無法讀取它,下一次讀取嘗試將再次設置EOF位。這是正常的嗎? ...你的解決方案聽起來不錯,但是當管道關閉時,我的服務器重置它的狀態,我必須先改變它。 – jdm

+0

是的,這似乎是正常的。問題是你不能以std :: getline()或其他讀取函數再次阻塞的方式重置狀態,就像它在打開fifo之後一樣(呃,是的,管道的另一端也應該重做 - 打開(在這種情況下你的服務器)。 – 0x0C4