использование QTextStream для чтения stdin неблокирующим способом
используя 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 после прочтения первой строки текста. Так, например, если я пишу 5 строк текста в поток stdin процесса, я только когда-либо читал первую строку.
в чем может быть проблема?
2 ответов
буфферизацию.
по умолчанию промывка после "\n". Если вы пишете 5 строк в свой процесс, ваш слот вызывается 5 раз. Если вы хотите избежать этого, вам нужно позвонить setbuf (stdin, _IOFBF). Но даже тогда не гарантируется, что вы можете читать произвольно большие объемы данных в одном куске.
Edit: вероятно, лучше использовать QTextStream:: atEnd() вместо select, так как QTextStream имеет свои собственные внутренние буферы.
Я нашел и пример в другом ответе, который подходит почти к этому вопросу и с полным и простым кодом:
https://stackoverflow.com/a/7389622/721929
Я использовал его для реализации приложения на основе консоли QT с текстовым меню для выбора пользователя.