9

Qt を使用して、stdin ストリームの内容をノンブロッキングで読み取ろうとしています。QSocketNotifier を使用して、ソケットが新しいデータを受信したときに警告します。通知機能のセットアップは次のようになります。

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

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

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

ご覧のとおり、select() システム コールを使用して、読み取るデータがなくなったことを知らせようとしています。ただし、実際には、テキストの最初の行を読んだ後に select() 呼び出しが 0 を返します。したがって、たとえば、プロセスの stdin ストリームに 5 行のテキストを書き込むと、最初の行しか読み取れません。

何が問題なのですか?

4

2 に答える 2

4

行のバッファリング。

デフォルトは「\n」の後のフラッシュです。プロセスに 5 行書き込むと、スロットは 5 回呼び出されます。それを避けたい場合は、setbuf(stdin, _IOFBF) を呼び出す必要があります。ただし、それでも、1 つのチャンクで大量のデータを任意に読み取ることができるとは限りません。

編集: QTextStream には独自の内部バッファーがあるため、select の代わりに QTextStream::atEnd() を使用することをお勧めします。

于 2009-08-13T15:29:41.100 に答える
1

この質問にほぼ適合する他の回答の例と、完全でシンプルなコードを見つけました。

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

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

于 2012-10-23T09:20:43.170 に答える