2009-08-13 15 views
7

Utilizzando Qt, sto tentando di leggere il contenuto dello stdin stream in modo non bloccante. Sto usando QSocketNotifier per avvisarmi quando il socket ha ricevuto alcuni nuovi dati. L'impostazione per il notificante è simile al seguente:utilizzando QTextStream per leggere lo stdin in modo non bloccante

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 i dati da leggere. Tuttavia, in pratica, ciò che sta accadendo è che la chiamata select() restituisce 0 dopo aver letto la prima riga di testo. Ad esempio, se scrivo 5 righe di testo nello stream stdin del processo, ho sempre letto solo la prima riga.

Quale potrebbe essere il problema?

+0

hai provato readAll invece di readLine? – Bob

+0

sì. Penso che usi atEnd() internamente per rilevare quando viene raggiunta la fine del flusso. Il risultato è che blocca per sempre. – Thomi

+1

ok, solo l'altra cosa che posso pensare di provare è rottamare l'implementazione corrente (la chiamata selezionata) e fare qualcosa di simile a ciò che fa l'assistente, vedere strumenti \ assistente \ strumenti \ assistente \ remotecontrol * – Bob

risposta

4

Buffering di linea.

Il valore predefinito è lo svuotamento dopo un "\ n". Se scrivi 5 linee sul tuo processo, il tuo slot viene chiamato 5 volte. Se vuoi evitarlo, devi chiamare setbuf (stdin, _IOFBF). Ma anche in questo caso non è garantito che tu possa leggere arbitrariamente grandi quantità di dati in un blocco.

Modifica: Probabilmente sarebbe meglio utilizzare QTextStream :: atEnd() invece di selezionare, poiché QTextStream ha i propri buffer interni.

+1

Non è possibile utilizzare QTextStream :: atEnd() su stdin - la documentazione Qt lo dice (consultare la documentazione dettagliata per la classe). Vedi: http://doc.trolltech.com/4.5/qtextstream.html#details – Thomi

1

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

ho usato per implementare un'applicazione console basata QT con un testo menu per scegliere sulla selezione dell'utente.

Problemi correlati