utilizzando QTextStream leggere stdin in un modo non bloccante
Domanda
Utilizzando Qt, sto cercando di leggere il contenuto del flusso stdin in un modo non-blocking. Sto utilizzando la QSocketNotifier per avvisare me quando il socket ha ricevuto alcuni nuovi dati. L'impostazione per il notificante è simile al seguente:
QSocketNotifier *pNot = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, this);
connect(pNot, SIGNAL(activated(int)), this, SLOT(onData()));
pNot->setEnabled(true);
Lo slot onData()
assomiglia a questo:
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;
}
Come potete vedere sto cercando di utilizzare la chiamata di sistema select () per dirmi quando ho esaurito di dati da leggere. Tuttavia, in pratica ciò che sta accadendo è la select () chiamata restituisce 0 dopo che ho letto la prima riga di testo. Così, per esempio, se scrivo 5 linee di testo al flusso stdin del processo, ho sempre e solo letto la prima riga.
Quale potrebbe essere il problema?
Soluzione
Linea buffering.
default è vampate di calore, dopo un "\ n". Se si scrive 5 linee al vostro processo, lo slot viene chiamato 5 volte. Se si vuole evitare che, si deve chiamare setbuf (stdin, _IOFBF). Ma anche in questo caso non è garantito che si può leggere arbitrariamente grandi quantità di dati in un unico pezzo.
Modifica: Sarebbe probabilmente meglio utilizzare QTextStream :: atend () invece di selezionare, dal momento QTextStream ha i suoi buffer interni
.Altri suggerimenti
ho trovato e l'esempio in altra risposta che si adatta quasi a questa domanda e con il codice completo e semplice:
https://stackoverflow.com/a/7389622/721929
L'ho usato per implementare un'applicazione console basata QT con un menu testuale di scegliere sulla selezione dell'utente.