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,容易引发栈溢出或堆内存分配失败,导致程序崩溃。
解决方案
核心思路是分块处理大文件和大字符串,避免一次性加载或传递超大规模数据:
- 分块读取原二进制文件,避免一次性将整个130MB数据加载到内存
- 手动创建
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
相关产品推荐
相关产品推荐

