QXMLStreamreader читает из медленного QProcess

В Qt 5.1 у меня возникла проблема с QXMLStreamReader, ожидающим, когда QProcess выдаст больше данных.

Если я читаю строки из небуферизованного QProcess, он работает нормально:

while(!vupProcess.state() == QProcess::NotRunning)
{
    if (vupProcess.atEnd())
    {
        vupProcess.waitForReadyRead();
    }
    qDebug() << vupProcess.readLine();
}

Это довольно ясно: когда в буфере нет данных, он ждет, пока их не станет больше. Когда будет больше, он будет печатать строки без ожидания.

Теперь, если я хочу сделать то же самое с QXMLStreamReader, он работает, но обработка элементов XML происходит в неправильный момент (слишком поздно).

Учти это:

QXmlStreamReader xml;
xml.setDevice(&vupProcess);
QStack<VUPDevice *> deviceStack;
QXmlStreamReader::TokenType tokenType = QXmlStreamReader::NoToken;

while (tokenType != QXmlStreamReader::EndDocument && !xml.hasError())
{
    if (xml.device()->atEnd())
    {
        xml.device()->waitForReadyRead(XML_READNEXT_TIMEOUT);
    }

    tokenType = xml.readNext();

    if (xml.hasError())
    {
        qDebug() << "ERROR";
        return;
    }

    ...
}

Тем временем waitForReadyRead(int) называется, многие элементы уже доступны, и мне нужно обработать их для обновления графического интерфейса. Однако, это не будет продолжаться, пока QProcess не начнет выводить больше. Кажется, это потому, что базовый QProcess читается до тех пор, пока он максимально быстро не опустошается, а затем мой анализатор излишне зависает на ранних стадиях, потому что QProcess больше не выводит.

Что мне нужно, так это xml.hasMoreElements()так что я могу сделать:

if (xml.device()->atEnd() && !xml.hasMoreElements())
{
    xml.device()->waitForReadyRead(XML_READNEXT_TIMEOUT);
}

Но я не могу найти вызов API, который делает это для меня.

Итак, как мне не ждать больше данных, когда это не нужно?

1 ответ

Решение

Я думаю, я решил это. Нет способа спросить, есть ли еще элементы XML, но readNext() вызов поставит QXMLStreamReader объект в состоянии, которое вы можете обнаружить и использовать для ожидания внутреннего устройства:

QXmlStreamReader::TokenType tokenType = xml.readNext();

while (xml.error() == QXmlStreamReader::PrematureEndOfDocumentError)
{
    xml.device()->waitForReadyRead(XML_READNEXT_TIMEOUT);
    tokenType = xml.readNext();
}

if (xml.hasError())
{
    ...
}
Другие вопросы по тегам