使用Qt5的QXmlStreamWriter和QXmlStreamReader实现xml文件的写入和读取
Qt中实现xml文件写入和读取操作的方法有多种,但是总体来说,还是接下来要介绍的方法更加的方便快捷。
需要说明的是:QXmlStreamReader和SAX的作用是一致的,前者是作为后者的替代品出现的,而DOM(文档对象模型)是W3C推荐的标准,它不同于前者一行一行地读取,而是一次性读取到内存中以树型结构的方式存储,方便操作和随机访问,灵活性高,但是代价是当文件较大时读取需要费些时间。
下面基于我在实际项目中的一个小需求,通过编写一个小demo来介绍该内容。
第1步:使用QXmlStreamWriter实现xml文件的写入操作
void writeXML() {
QFile file("../generateConfigureInfoFile/bg_train01.xml");
if(!file.open(QFile::WriteOnly | QFile::Text | QFile::Truncate)) {
qDebug() << "failed to open bg_train01.xml";
return;
}
QXmlStreamAttributes attributes;
QXmlStreamWriter writer;
writer.setCodec("UTF-8");
writer.setDevice(&file);
writer.setAutoFormatting(true);
writer.writeStartDocument(); //编写文档的第一行
writer.writeStartElement("ConfigInfo");
writer.writeComment("开始保存第1行的配置数据!");
writer.writeStartElement("RootDir");
attributes.append("itemText", "BG-HAO(2873/2873)");
attributes.append("dirBaseName", "BG-HAO");
attributes.append("withSubDir", "false");
attributes.append("showSubDir", "false");
writer.writeAttributes(attributes);
writer.writeStartElement("SubDir");
attributes.clear();
attributes.append("itemText", "/");
attributes.append("dirBaseName", "BG-HAO");
attributes.append("withSubDir", "false");
attributes.append("showSubDir", "false");
writer.writeAttributes(attributes);
writer.writeTextElement("ImageSum", "2873");
writer.writeEmptyElement("DirInfo");
attributes.clear();
attributes.append("dirFullName", "/home/liuqiang/Documents/BG/train/BG-HAO");
attributes.append("imageNumber", "2873");
writer.writeAttributes(attributes);
writer.writeTextElement("Weight", "1.0");
writer.writeEmptyElement("Label");
attributes.clear();
attributes.append("name", "(0)hao");
attributes.append("color", "#12ec76");
attributes.append("number", "0");
writer.writeAttributes(attributes);
writer.writeEndElement();
writer.writeEndElement();
writer.writeComment("第1行的配置数据保存完毕!");
writer.writeComment("开始保存第2行的配置数据!");
writer.writeStartElement("RootDir");
attributes.clear();
attributes.append("itemText", "BG-CHA(4222/4222)");
attributes.append("dirBaseName", "BG-CHA");
attributes.append("withSubDir", "false");
attributes.append("showSubDir", "false");
writer.writeAttributes(attributes);
writer.writeStartElement("SubDir");
attributes.clear();
attributes.append("itemText", "/");
attributes.append("dirBaseName", "BG-CHA");
attributes.append("withSubDir", "false");
attributes.append("showSubDir", "false");
writer.writeAttributes(attributes);
writer.writeTextElement("ImageSum", "4222");
writer.writeEmptyElement("DirInfo");
attributes.clear();
attributes.append("dirFullName", "/home/liuqiang/Documents/BG/train/BG-CHA");
attributes.append("imageNumber", "4222");
writer.writeAttributes(attributes);
writer.writeTextElement("Weight", "1.0");
writer.writeEmptyElement("Label");
attributes.clear();
attributes.append("name", "(1)cha");
attributes.append("color", "#0cc8f3");
attributes.append("number", "1");
writer.writeAttributes(attributes);
writer.writeEndElement();
writer.writeEndElement();
writer.writeComment("第2行的配置数据保存完毕!");
writer.writeComment("开始保存第3行的配置数据!");
writer.writeStartElement("RootDir");
attributes.clear();
attributes.append("itemText", "train(7095/7095)");
attributes.append("dirBaseName", "train");
attributes.append("withSubDir", "true");
attributes.append("showSubDir", "false");
writer.writeAttributes(attributes);
writer.writeStartElement("SubDir");
attributes.clear();
attributes.append("itemText", "/");
attributes.append("dirBaseName", "train");
attributes.append("withSubDir", "true");
attributes.append("showSubDir", "false");
writer.writeAttributes(attributes);
writer.writeTextElement("ImageSum", "7095");
writer.writeEmptyElement("DirInfo");
attributes.clear();
attributes.append("dirFullName", "/home/liuqiang/Documents/BG/train/BG-HAO");
attributes.append("imageNumber", "2873");
writer.writeAttributes(attributes);
writer.writeEmptyElement("DirInfo");
attributes.clear();
attributes.append("dirFullName", "/home/liuqiang/Documents/BG/train/BG-CHA");
attributes.append("imageNumber", "4222");
writer.writeAttributes(attributes);
writer.writeTextElement("Weight", "1.0");
writer.writeEmptyElement("Label");
attributes.clear();
attributes.append("name", "(0)hao");
attributes.append("color", "#12ec76");
attributes.append("number", "0");
writer.writeAttributes(attributes);
writer.writeEndElement();
writer.writeEndElement();
writer.writeComment("第3行的配置数据保存完毕!");
writer.writeComment("开始保存第4行的配置数据!");
writer.writeStartElement("RootDir");
attributes.clear();
attributes.append("itemText", "train(7095/7095)");
attributes.append("dirBaseName", "train");
attributes.append("withSubDir", "true");
attributes.append("showSubDir", "true");
writer.writeAttributes(attributes);
writer.writeStartElement("SubDir");
attributes.clear();
attributes.append("itemText", "BG-HAO(2873/2873)");
attributes.append("dirBaseName", "BG-HAO");
attributes.append("withSubDir", "false");
attributes.append("showSubDir", "false");
writer.writeAttributes(attributes);
writer.writeTextElement("ImageSum", "2873");
writer.writeEmptyElement("DirInfo");
attributes.clear();
attributes.append("dirFullName", "/home/liuqiang/Documents/BG/train/BG-HAO");
attributes.append("imageNumber", "2873");
writer.writeAttributes(attributes);
writer.writeTextElement("Weight", "1.0");
writer.writeEmptyElement("Label");
attributes.clear();
attributes.append("name", "(1)cha");
attributes.append("color", "#0cc8f3");
attributes.append("number", "1");
writer.writeAttributes(attributes);
writer.writeEndElement();
writer.writeStartElement("SubDir");
attributes.clear();
attributes.append("itemText", "BG-CHA(4222/4222)");
attributes.append("dirBaseName", "BG-CHA");
attributes.append("withSubDir", "false");
attributes.append("showSubDir", "false");
writer.writeAttributes(attributes);
writer.writeTextElement("ImageSum", "4222");
writer.writeEmptyElement("DirInfo");
attributes.clear();
attributes.append("dirFullName", "/home/liuqiang/Documents/BG/train/BG-CHA");
attributes.append("imageNumber", "4222");
writer.writeAttributes(attributes);
writer.writeTextElement("Weight", "1.0");
writer.writeEmptyElement("Label");
attributes.clear();
attributes.append("name", "(1)cha");
attributes.append("color", "#0cc8f3");
attributes.append("number", "1");
writer.writeAttributes(attributes);
writer.writeEndElement();
writer.writeEndElement();
writer.writeComment("第4行的配置数据保存完毕!");
writer.writeEndElement();
file.close();
}
第2步:使用QXmlStreamReader实现xml文件的读取操作
void readXML() {
QFile file("../generateConfigureInfoFile/bg_train01.xml");
if(!file.open(QFile::ReadOnly | QFile::Text)) {
qDebug() << "failed to open bg_train01.xml";
return;
}
QXmlStreamReader reader;
reader.setDevice(&file);
reader.readNext();
if(reader.isStartDocument()){
QString version = reader.documentVersion().toString();
QString encoding = reader.documentEncoding().toString();
bool isAlone = reader.isStandaloneDocument();
qDebug() << "Version: " << version << "; Encoding: " << encoding << "Standalone: " << isAlone;
reader.readNext();
}
while (!reader.atEnd()) { //如果没有读到文档结尾,而且没有出现错误
if(reader.isStartElement()) {
if(reader.name() == "ConfigInfo") {
qDebug() << "start reading: " << reader.name();
reader.readNext();
}
else if(reader.name() == "RootDir") {
qDebug() << reader.name()
<< reader.attributes().value("itemText")
<< reader.attributes().value("dirBaseName")
<< reader.attributes().value("withSubDir")
<< reader.attributes().value("showSubDir");
reader.readNext();
}
else if(reader.name() == "SubDir") {
qDebug() << reader.name()
<< reader.attributes().value("itemText")
<< reader.attributes().value("dirBaseName")
<< reader.attributes().value("withSubDir")
<< reader.attributes().value("showSubDir");
reader.readNext();
}
else if(reader.name() == "ImageSum") {
qDebug() << reader.name() << reader.readElementText().toInt();
reader.readNext();
}
else if(reader.name() == "DirInfo") {
qDebug() << reader.name() << reader.attributes().value("dirFullName")
<< reader.attributes().value("imageNumber");
reader.readNext();
}
else if(reader.name() == "Weight") {
qDebug() << reader.name() << reader.readElementText().toFloat();
reader.readNext();
}
else if(reader.name() == "Label") {
qDebug() << reader.name()
<< reader.attributes().value("name")
<< reader.attributes().value("color")
<< reader.attributes().value("number");
reader.readNext();
}
else {
reader.readNext();
}
}
else if(reader.isComment()) {
qDebug() << reader.text(); //读取注释内容
reader.readNext();
}
else if(reader.isEndElement()) {
reader.readNext();
}
else {
reader.readNext();
}
if (reader.hasError()) { //如果读取过程中出现错误,那么输出错误信息
qDebug() << "error: " << reader.errorString();
}
}
file.close();
}
调用写入和解析函数
int main() {
writeXML();
readXML();
return 0;
}
在我的机器上运行结果如下:
使用QXmlStreamWriter写入的结果截图:
使用QXmlStreamReader读取的结果截图: