You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QXmlStreamWriter的writeTextElement写入大文件时崩溃问题求助

Qt 4.8.7中QXmlStreamWriter写入大Base64内容崩溃的解决方案

问题场景

写入130MB二进制文件转Base64后,通过QXmlStreamWriter::writeTextElement写入XML时程序崩溃,但处理2MB大小的文件时运行正常。

环境信息

  • Qt开源版4.8.7
  • Visual Studio 2010
  • Windows 10

原崩溃代码

#include <QtCore/QCoreApplication>
#include <QFile>
#include <QXmlStreamWriter>


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QByteArray mContentBuffer;

    QFile file("C:\\Work\\bigfile.xar");
   
    if(!file.open(QFile::ReadOnly))
    {
        return -1;
    }

    mContentBuffer = file.readAll();
    file.close();

    QFile profile("C:\\Work\\profile.xml");

    if(!profile.open(QFile::WriteOnly|QFile::Truncate))
    {
        return -1;
    }

    QXmlStreamWriter stream(&profile);    

    stream.setAutoFormatting(true);
    stream.writeStartDocument();
    stream.writeStartElement("Profile");

    stream.writeTextElement("Content", mContentBuffer.toBase64());

    stream.writeEndElement(); // Profile
    stream.writeEndDocument();

    return a.exec();
}

崩溃截图

崩溃原因

Qt 4.8版本的writeTextElement在处理超大规模字符串时,内部单次传递的字符串长度超出内存处理阈值。130MB二进制数据转Base64后体积会膨胀约33%,达到170MB左右,一次性将该字符串传入writeTextElement,容易引发栈溢出或堆内存分配失败,导致程序崩溃。

解决方案

核心思路是分块处理大文件和大字符串,避免一次性加载或传递超大规模数据:

  1. 分块读取原二进制文件,避免一次性将整个130MB数据加载到内存
  2. 手动创建Content标签,分块将二进制数据转Base64后通过writeCharacters写入,替代一次性调用writeTextElement

修改后的代码

#include <QtCore/QCoreApplication>
#include <QFile>
#include <QXmlStreamWriter>
#include <QByteArray>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QFile file("C:\\Work\\bigfile.xar");
    if(!file.open(QFile::ReadOnly))
    {
        return -1;
    }

    QFile profile("C:\\Work\\profile.xml");
    if(!profile.open(QFile::WriteOnly|QFile::Truncate))
    {
        file.close();
        return -1;
    }

    QXmlStreamWriter stream(&profile);    
    stream.setAutoFormatting(true);
    stream.writeStartDocument();
    stream.writeStartElement("Profile");

    // 手动启动Content标签,而非使用writeTextElement
    stream.writeStartElement("Content");

    // 1MB分块读取并写入,可根据内存情况调整块大小
    const qint64 chunkSize = 1024 * 1024;
    QByteArray chunk;
    while(!file.atEnd())
    {
        chunk = file.read(chunkSize);
        // 分块写入Base64内容
        stream.writeCharacters(chunk.toBase64());
    }

    stream.writeEndElement(); // 闭合Content标签
    stream.writeEndElement(); // 闭合Profile标签
    stream.writeEndDocument();

    // 确保文件资源关闭
    file.close();
    profile.close();

    return a.exec();
}

代码说明

  • 分块读取:每次读取1MB二进制数据,大幅降低内存占用,避免一次性加载大文件导致的内存压力
  • 分块写入:通过writeCharacters分块输出Base64内容,规避writeTextElement单次处理超大规模字符串的限制
  • 资源管理:异常分支中增加文件关闭操作,避免资源泄漏

内容的提问来源于stack exchange,提问作者Ming

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 08:23:55