2009-08-13 6 views
7

Qtを使って、stdinストリームの内容を非ブロック的に読み込もうとしています。 QSocketNotifierを使用して、ソケットに新しいデータが受信されたときに警告します。あなたは、私がとき私に教えてselect()システムコールを使用しようとしています見ることができるようにQTextStreamを使ってstdinをノンブロッキングで読む

void CIPCListener::onData() 
{ 
    qDebug() << Q_FUNC_INFO; 
    QTextStream stream(stdin, QIODevice::ReadOnly); 

    QString str; 

    forever 
    { 
     fd_set stdinfd; 
     FD_ZERO(&stdinfd); 
     FD_SET(STDIN_FILENO, &stdinfd); 
     struct timeval tv; 
     tv.tv_sec = 0; 
     tv.tv_usec = 0; 
     int ready = select(1, &stdinfd, NULL, NULL, &tv); 
     if(ready > 0) 
     { 
      str += stream.readLine(); 
     } 
     else 
     { 
      break; 
     } 
    } 

    qDebug() << "Recieved data:" << str; 
} 

onData()スロットは次のようになります

QSocketNotifier *pNot = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, this); 
connect(pNot, SIGNAL(activated(int)), this, SLOT(onData())); 
pNot->setEnabled(true); 

:通知の設定は次のようになります私は読むためにデータを使い果たしました。しかし実際には、select()呼び出しはテキストの最初の行を読んだ後に0を返します。たとえば、5行のテキストをプロセスの標準入力ストリームに書き込むと、最初の行だけが読み込まれます。

何が問題なのですか?

+0

あなたはreadLineの代わりにreadAllを試しましたか? – Bob

+0

はい。私はそれがストリームの終わりに達した時を検出するためにatEnd()を内部的に使用すると思います。結局のところ、それは永遠にブロックされます。 – Thomi

+1

私が思うことができる他のことは、現行の実装(選択呼び出し)を廃止し、同意するものに似た何かをすることです。tools \ assistant \ tools \ assistant \ remotecontrol * – Bob

答えて

4

ラインバッファリング。

デフォルトでは、 "\ n"の後にフラッシングしています。プロセスに5行を書き込むと、スロットは5回呼び出されます。それを避けたい場合は、setbuf(stdin、_IOFBF)を呼び出さなければなりません。しかしそれでも、あるチャンク内の任意の大量のデータを読み取ることが保証されているわけではありません。

編集:QTextStreamには独自の内部バッファがあるので、selectではなくQTextStream :: atEnd()を使用する方がよいでしょう。

+1

QTextStream :: atEnd()をstdinで使用することはできません。Qtのドキュメントにはこう書かれています(クラスの詳細なドキュメントを参照)。参照: http://doc.trolltech.com/4.5/qtextstream.html#details – Thomi

1

私が見つけたとの例はほとんどこの質問に、完全な、簡単なコードでフィットし、他の答えに:

https://stackoverflow.com/a/7389622/721929

私は、テキストとQTコンソールベースのアプリケーションを実装するためにそれを使用しましたユーザー選択を選択するメニュー。

関連する問題