2017-06-05 83 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