2017-06-05 11 views
2

std::ifstream::readを使用してパイプ(Linux)またはパイプ状のデバイスオブジェクト(Windows)から読み込み中です。ただし、データがなくなると、readは0バイトを読み取り、EOFと設定します。 ifstreamからブロッキングを読み取る方法はありますか?それ以上のデータがある場合にのみ返されます。std :: ifstreamからブロックする

私はむしろEOFフラグがクリアされるのを待っていません。

C++標準ライブラリでは不可能な場合、最も近い他のオプションは何ですか?私はそれをC言語で行うことができますか、あるいはオペレーティングシステム固有のAPIに頼らなければなりませんか?

答えて

3

残念ながら、stdは、IOのようなアルゴリズム以外の機能では非常に悪いです。常にサードパーティのソリューションに依存する必要があります。幸いにも、Boostがありますので、OS固有のコードを減らすために使用することをお勧めします。基本となるストリームデバイスとして動作し、内部のWindowsまたはPOSIX特定パイプを隠しIはBoost IO Streamsを使用して、具体的file_descriptor_sourceこの小さな例で

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 

。パイプは自分で開きますので、パイプを必要に応じて構成できます。

+0

ありがとう、私はそれを試してみましょう。残念ながら、WindowsにBoostをインストールすることは、WinApiですべてを書き始めるだけで複雑になります;-)。 – jdm

+0

MinGWを使用している場合は、このパッケージリポジトリ[Alexpux Packages](https://github.com/Alexpux/MINGW-packages)に基づいて 'packman'を使用してインストールすることができます。 – 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()やその他のread関数がFIFOを開いた後に再びブロックするような状態ではリセットできないということです:(もちろん、パイプのもう一方の端はre -open(その場合はサーバー)。 – 0x0C4

関連する問題