Ошибка при загрузке больших файлов с помощью setContent(&file) в парсере qt DOM xml

Я сталкиваюсь со странной проблемой, которую не могу решить. Кажется, ни у кого нет этой проблемы. При загрузке небольшого XML-файла (4 МБ) все нормально, и программа работает нормально, но когда я пытаюсь загрузить больший файл (200 МБ), программа вылетает без ошибок (даже в режиме отладки). Он также не распечатывает сообщения об ошибках, так как программа вылетает до их вызова. Спасибо за помощь.

Журнал ошибок от создателя QT:

Программа неожиданно завершилась. C:/Parser [путь]/XmlDOM упал

Код:

QFile file("./file.osm");
qDebug() << file.exists();
qDebug() << file.size();

QString errorStr;
int errorLine;
int errorColumn;

QDomDocument document;

if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
    qDebug() << "Failed to open file";
    return -1;
}
else
{
    if(!document.setContent(&file, false, &errorStr, &errorLine, &errorColumn)) //here the programm crashes
    {
        std::cerr << "Error: Parse error at line " << errorLine << ", "
                          << "column " << errorColumn << ": "
                          << qPrintable(errorStr) << std::endl;
       return -1;
    }
    qDebug() << file.isReadable(); //with small files this becomes true 
    file.close();
    } 
QDomElement root = document.firstChildElement();

Решение:

Активируйте раздел подкачки или получите больше оперативной памяти, программа зависает, потому что на компьютере не хватает памяти. Обновления оставлены в вопросе только для того, чтобы документировать мои дальнейшие действия.

Обновление: я установил все на другой машине. Теперь я получаю вывод:

Ошибка: ошибка разбора в строке 1, столбец 1: неожиданный конец файла

Забавно, что теперь даже маленькие файлы не работают и возвращают ошибку. После некоторых копаний некоторые люди неправильно указали путь к файлу, поэтому я проверил свой путь.

qDebug() << "File exists: " << file.exists(); 
qDebug() << "File path: " << QFileInfo(file).absoluteFilePath();
qDebug() << "File size: " << file.size();    

Возвращает: true, /path/to/file/file.osm, правильный размер

Я также проверил, являются ли мои файлы XML действительными, и они являются. Итак, какие-нибудь новые предложения? Пока я застрял

Update2: сначала спасибо за ваши ответы! Одна отчаянная попытка была:

else{
  document.setContent(&file); //passed and worked, funny
}
qDebug() << file.isReadable(); 
file.close();

Это наконец работает с большими и меньшими файлами на новой установке:

else
{

    if(!document.setContent(&file))
    {
       std::cerr << "Error: Open file "<< std::endl;
       return -1;
    }
    qDebug() << file.isReadable(); 
    file.close();

Почему я использовал DOM Parser: XML-структура выглядит так:

<osm>
    <node id ="1" lat="value", lon="value" />
    <node id ="2" lat="value", lon="value" />
    <node id ="3" lat="value", lon="value" />

    <way id="12345">
      <nd ref ="1"/>
      <nd ref ="2"/>
      <nd ref ="3"/>
    </way>
</osm>

Я хочу перестроить точки пути, для которых необходимы значения lat, lon из узлов. Для этого я хочу иметь возможность сопоставить путь ID с идентификатором узла и получить значения в пути. Является ли Sax-парсер лучшим решением для этого? Я работал с деревом DOM, я мог бы легко пройти через "узлы" и сопоставить идентификаторы без повторного анализа полного XML. Я использую Ubuntu и с новой настройкой qt5. Я получил i5 2-го поколения и 8 ГБ оперативной памяти, которые заполнены во время обработки большого файла. Один запуск в режиме выпуска требует 50 минут на 1000 трасс с 5-50 узлами.

2 ответа

Решение

Решение состоит в том, чтобы активировать раздел подкачки или получить больше оперативной памяти, программа зависла, потому что на компьютере не было / не было оперативной памяти. Еще лучшим решением является использование парсера SAX.

Проблема времени выполнения: используйте карты вместо векторов. Время выполнения уменьшилось до ~20 секунд для большого файла.

Пакет Qt XML и QDomDocument не должен использоваться с очень большими документами XML.

Предмет QDomDocument сохраняет всю структуру XML-документа в оперативной памяти. Это решающий порог 200MB для размера файла XML, так как с такими файлами QDomDocument можешь использовать 2GB или ОЗУ.

Доступные выпуски Qt4 для Windows построены с 32-битными компиляторами. Таким образом, это предел для таких приложений, например. Сколько памяти может получить доступ к 32-битному процессу в 64-битной операционной системе?

В целом, все большие XML-документы не должны загружаться в ОЗУ. Такие документы должны обрабатываться потоковыми парсерами.

С другой стороны, если документ XML не намного больше, чем 200MB и проект уже работает с QDomDocument и на компьютере достаточно оперативки (8GB - 16GB) можно скомпилировать проект с использованием 64-битных компиляторов. В этом случае Qt4 должен быть скомпилирован вручную. Также Release сборка может использовать в два раза меньше оперативной памяти, чем Debug,

Другие вопросы по тегам