Чтение 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, который сделает это за меня.

Итак, как мне не ждать дополнительных данных, когда в них нет необходимости?


person Halfgaar    schedule 02.12.2013    source источник


Ответы (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())
{
    ...
}
person Halfgaar    schedule 02.12.2013