QT5——xml文件的读写

1、使用流QXmlStreamReader、QXmlStreamWriter读写xml文件

项目的pro文件里面添加:

QT       +=core xml

用QXmlStreamReader读取xml文本内容

在路径C:\Users\Administrator\Desktop\ZGXIPCDemo中存放device.xml文件。内容以及各式如下:
QT5——xml文件的读写_第1张图片使用qDebug()显示读取文件的内容

#include
#include
#include
#include

void query_dev_xml(QString dev_xml_dir); //查询xml,dev_xml_dir是xml文件的存放地址
//查询制定的.xml中相应信息,显示在终端
//dev_xml_dir .xml文件的存放地址
void devmanager::query_dev_xml(QString dev_xml_dir) //查询xml
{
    QFile file(dev_xml_dir);//
    if(!file.open(QFile::ReadOnly|QFile::Text))
    {
        qDebug()<<"cannot open file";
    }
    else {
        qDebug()<<"file opened!";
    }
    QXmlStreamReader reader;
    reader.setDevice(&file);
    while(!reader.atEnd())
    {
        QXmlStreamReader::TokenType type =reader.readNext();
        //根据记号的类型进行输出
        if (type==QXmlStreamReader::StartElement)
        {
            qDebug()<<"start element:"<<reader.name()<<"reader.text:"<<reader.text();
            if(reader.attributes().hasAttribute("id"))
            {
                qDebug()<<"has attribute device id="<<reader.attributes().value("id");
                qDebug()<<"version"<<reader.attributes().value("version");
                qDebug()<<"password: "<<reader.attributes().value("password");
                qDebug()<<"username: "<<reader.attributes().value("username");
                qDebug()<<"channelno: "<<reader.attributes().value("channelno");
                qDebug()<<"port: "<<reader.attributes().value("port");
                qDebug()<<"ip: "<<reader.attributes().value("ip");
                qDebug()<<"type: "<<reader.attributes().value("type");
                qDebug()<<"name: "<<reader.attributes().value("name");
                qDebug()<<"id: "<<reader.attributes().value("id");
            }
            else
            {
                 qDebug()<<"element has no id";
            }
        }

        if(type==QXmlStreamReader::EndElement)
            qDebug()<<" end element: "<<reader.name();
        if (type==QXmlStreamReader::Characters&&!reader.isWhitespace())
            qDebug()<<"Characters and is whitespace: "<<reader.text();
    }

    file.close();
}

运行结果如下:
QT5——xml文件的读写_第2张图片

使用QXmlStreamWriter编写xml文件

1、直接填写具体信息

void write_dev_xml(QString dev_xml_dir);  //写入xml数据,其它设置同上
//将设备信息写入.xml文件中
//dev_xml_dir:.xml文件地址  devinfo:设备信息
void devmanager::write_dev_xml(QString dev_xml_dir)//, dev_info devinfo
{
    QFile file(dev_xml_dir);//
    if(!file.open(QFile::WriteOnly|QFile::Text|QFile::Truncate))
    {
        qDebug()<<"cannot open file to write";
    }
    else
    {
        qDebug()<<"write file opened!";
    }

    QXmlStreamWriter writer;
   // QXmlStreamReader reader;  //
    QXmlStreamAttributes attributes;   //QXmlStreamAttributes,而非QXmlStreamAttribute

    writer.setCodec("UTF-8");
    writer.setDevice(&file);
    writer.setAutoFormatting(true);//自动格式
    //attributes.clear();
    writer.writeStartDocument();
    writer.writeStartElement("root");

       writer.writeStartElement("device");

       attributes.append("version"," "); //由""修改为" ",否则生成文件内容空白
       attributes.append("password","admin508");
       attributes.append("username","admin");
       attributes.append("channelno","0");
       attributes.append("port","8080");
       attributes.append("ip","1.1.1.1");
       attributes.append("type","0");
       attributes.append("name","costarIPC");
       attributes.append("id","0");
       writer.writeAttributes(attributes);
       writer.writeEndElement();

     writer.writeEndElement();
     writer.writeEndDocument();
     file.close();
     qDebug()<<"finished writing!";
}

运行结果:
在这里插入图片描述2、使用结构体保存相关信息
此处需要保存的信息结构一直,所以采用结构体。

//.h文件中定义
typedef struct{
    QString version;
    QString password;
    QString username;
    QString channelno;
    QString port;
    QString ip;
    QString type;
    QString name;
    QString id;
}dev_info ;

void write_dev_xml_struct(QString dev_xml_dir,dev_info devinfo);//用结构体dev_info devinfo写入数据
 dev_info devinfo;//使用定义的设备参数结构体

   //自定义一个设备信息用于写入、读出测试
   devinfo.id=QString("1");
   devinfo.ip=QString("100,100,100,100");
   devinfo.name=QString("test1");
   devinfo.port=QString("8000");
   devinfo.type=QString("0");
   devinfo.version=QString("1");
   devinfo.password=QString("1");
   devinfo.username=QString("test_user_1");
   devinfo.channelno=QString("1");
//
//用结构体导入数据
//dev_xml_dir:生成的xml文件地址   devinfo:以结构体形式存储的具体信息
void devmanager::write_dev_xml_struct(QString dev_xml_dir,dev_info devinfo)//
{
    QFile file(dev_xml_dir);//
    if(!file.open(QFile::WriteOnly|QFile::Text|QFile::Truncate))
    {
        qDebug()<<"cannot open file to write";
    }
    else
    {
        qDebug()<<"write file opened!";
    }

    QXmlStreamWriter writer;
    QXmlStreamAttributes attributes;   //QXmlStreamAttributes,而非QXmlStreamAttribute
    writer.setCodec("UTF-8");
    writer.setDevice(&file);
    writer.setAutoFormatting(true);//自动格式
    
    writer.writeStartDocument();
    writer.writeStartElement("root");
       writer.writeStartElement("device");

           qDebug()<<"for"<<devinfo.version;  //for "1"
          attributes.append("version",devinfo.version);
          attributes.append("password",devinfo.password);
          attributes.append("username",devinfo.username);
          attributes.append("channelno",devinfo.channelno);
          attributes.append("port",devinfo.port);
          attributes.append("ip",devinfo.ip);
          attributes.append("type",devinfo.type);
          attributes.append("name",devinfo.name);
          attributes.append("id",devinfo.id);

       writer.writeAttributes(attributes);
       writer.writeEndElement();

     writer.writeEndElement();
     writer.writeEndDocument();
     file.close();
     qDebug()<<"finished writing!";
}

https://www.qter.org/forum.php?mod=viewthread&tid=11953
https://blog.csdn.net/l1216766050/article/details/84935752

2、使用QDomDocument实现文件的读写,增删改查

上面使用的流不能实现增删的功能

新建xml
#include //
#include//
void write_dom_xml(QString dev_xml_dir);//写入
//使用QDomDocument将数据写入xml
//dev_xml_dir:xml文件地址
void devmanager::write_dom_xml(QString dev_xml_dir)
{
    QFile file(dev_xml_dir);//用绝对、相对路径打开文件
    if(!file.open(QFile::WriteOnly|QFile::Truncate))//Truncate表示清空原来的内容
    {
        qDebug()<<"open xml failed!";
    }

    QDomDocument doc;
    QDomProcessingInstruction instruction;
    instruction=doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild(instruction);

    //添加根节点
    QDomElement root=doc.createElement("root");
    doc.appendChild(root);

    //添加第一个子节点device及其子元素
    QDomElement device=doc.createElement("device");
    device.setAttribute("id",0); //方式一:创建属性  其中键值对的值可以是各种类型

    QDomAttr name=doc.createAttribute("name"); //方式二:创建属性 值必须是字符串
    name.setValue("costarIPC");
    device.setAttributeNode(name);

     device.setAttribute("type","0");
     device.setAttribute("ip","1.1.1.1");
     device.setAttribute("port","0");
     device.setAttribute("channelno","0");
     device.setAttribute("username","admin");
     device.setAttribute("password","admin508");
     device.setAttribute("version"," ");

     root.appendChild(device);
     QTextStream output_stream(&file);
     doc.save(output_stream,4);//缩进4格
     file.close();
}

所有的节点用doc.createElement()创建,然后用appendchild将其添加到目标节点后面。

读取xml文件
void read_dom_xml(QString dev_xml_dir);//其它设置同上
//读取.xml文件
//dev_xml_dir:xml文件地址
void devmanager::read_dom_xml(QString dev_xml_dir)
{
    QFile file(dev_xml_dir);  //打开
    if(!file.open(QFile::ReadOnly))
    {
        qDebug()<<"failed to open!";
    }
    else
    {
        qDebug()<<"open file!";
    }

    QDomDocument doc;
    if(!doc.setContent(&file)) //读取
    {
        file.close();
        qDebug()<<"failed";
    }

    file.close();

    QDomElement root=doc.documentElement();//返回根节点
    qDebug()<<"root.nodename: "<<root.nodeName();  //root
    QDomNode node=root.firstChild();
    qDebug()<<"root.firstchild:"<<node.nodeName();   //device
    while(!node.isNull())
    {
        if(node.isElement())
        {
            QDomElement element=node.toElement();  //device由node转为element
            qDebug()<<"elemnt.tagname: "<<element.tagName();

            for(int i=0;i<element.attributes().count();i++)
            {
                QDomNode attribute=element.attributes().item(i);
                qDebug()<<attribute.nodeName()<<" : "<<attribute.nodeValue();
            }
            QDomNodeList nodelist=element.childNodes();//device下没有子节点,所以以下不会执行
            for(int i=0;i<nodelist.count();i++)
            {
                QDomNode nod=nodelist.at(i);
                qDebug()<<"nodelist.count= "<<nodelist.count()<<"at "<<i;
                if(nod.isElement())
                {
                    qDebug()<<nod.nodeName()<<":"<<nod.toElement().text();
                }
            }

        }
        node=node.nextSibling();//下一个兄弟节点,nextSiblingElement()是下一个兄弟元素
    }
}

运行结果:
QT5——xml文件的读写_第3张图片

增加一行元素

void add_dom_xml(QString dev_xml_dir);//增加,其它设置同上
//在已有的xml文件中添加新一行元素
//dev_xml_dir:xml文件地址
void devmanager::add_dom_xml(QString dev_xml_dir)//,dev_info devinfo
{
    //打开文件
    QFile file(dev_xml_dir);
    if(!file.open(QFile::ReadOnly))
    {
        qDebug()<<"failed to open file!";
    }
    else
    {
        qDebug()<<"open file!";
    }

    QDomDocument doc;
    if(!doc.setContent(&file))
    {
       qDebug()<<"doc.setconten";
    }
     file.close();

     //找到节点,添加元素
     QDomElement root=doc.documentElement();//根节点
     QDomElement device_add=doc.createElement("device");//1级子节点
      device_add.setAttribute("id","2"); //
      device_add.setAttribute("name","costarIPC2");
      device_add.setAttribute("type","0");
      device_add.setAttribute("ip","2.2.2.2");
      device_add.setAttribute("port","2");
      device_add.setAttribute("channelno","2");
      device_add.setAttribute("username","admin2");
      device_add.setAttribute("password","admin222");
      device_add.setAttribute("version"," ");

      root.appendChild(device_add);

      if(!file.open(QFile::WriteOnly|QFile::Truncate))//先读进来,再用truncate重写
      {
          qDebug()<<"open failed to truncate";
      }
      QTextStream output_stream(&file);
      doc.save(output_stream,4);//缩进4格
      file.close();
}

在这里插入图片描述

删除一行元素

void rem_dom_xml(QString dev_xml_dir);//删除,其它设置同上
//从xml文档中删除一行元素
//dev_xml_dir:xml文件地址
void devmanager::rem_dom_xml(QString dev_xml_dir)
{
    //打开
    QFile file(dev_xml_dir);
    if(!file.open(QFile::ReadOnly))
    {
        qDebug()<<"failed to open!";
    } else
    {
        qDebug()<<"opend!";
    }
    QDomDocument doc;
    if(!doc.setContent(&file))
    {
        qDebug()<<"doc.setcontent";
    }
    file.close();

    QDomElement root=doc.documentElement();
    QDomNodeList no_list=doc.elementsByTagName("device");
    for(int i=0;i<no_list.count();i++)
    {
        QDomElement element=no_list.at(i).toElement();//将device由node转换为element
        if(element.attribute("id")=="2")
        {
            root.removeChild(no_list.at(i));//此处的element为device,是root的child
        }
    }
    if(!file.open(QFile::WriteOnly|QFile::Truncate))
    {
        qDebug()<<"failed to write!";
    }
    QTextStream output_stream(&file);
    doc.save(output_stream,4);
    file.close();
}

QT5——xml文件的读写_第4张图片
以序号判断元素不可行,因为xml显示的顺序和xml结构里的节点顺序是不一致的。
QT5——xml文件的读写_第5张图片

void devmanager::update_dom_xml(QString dev_xml_dir)
{
    QFile file(dev_xml_dir);
    if(!file.open(QFile::ReadOnly))
    {
        qDebug()<<"failed to open!";
    }
    else
    {
        qDebug()<<"opened!";
    }

    QDomDocument doc;
    if(!doc.setContent(&file))
    {
        qDebug()<<"failed doc.setcontent";
    }
    file.close();

    QDomElement root=doc.documentElement();
    QDomNodeList list=root.elementsByTagName("device"); //2行device数据
    QDomNode node=list.at(0);                        //id=0的device行
    qDebug()<<"device.list(0):"<<node.nodeName();    //device

     QDomElement node_ele=node.toElement();
       qDebug()<<"new value"<<node_ele.attribute("name");
     node_ele.setAttribute("name","tttest");
     qDebug()<<"new value"<<node_ele.attribute("name");

    if(!file.open((QFile::WriteOnly|QFile::Truncate)))
    {
        return;
    }
    QTextStream output_stream(&file);
    doc.save(output_stream,4);
    file.close();
}

修改元素

void update_dom_xml(QString dev_xml_dir,dev_info devinfo);// 更新
//新的数据行,更换旧的数据行
//dev_xml_dir:xml文件地址  devinfo:设备信息
void devmanager::update_dom_xml(QString dev_xml_dir,dev_info devinfo)
{
    QFile file(dev_xml_dir);
    if(!file.open(QFile::ReadOnly))
    {
        qDebug()<<"failed to open!";
    }
    else
    {
        qDebug()<<"opened!";
    }

    QDomDocument doc;
    if(!doc.setContent(&file))
    {
        qDebug()<<"failed doc.setcontent";
    }
    file.close();

    //根据devinfo的信息形成新的node
    QDomElement attributes=doc.createElement("device");
          attributes.setAttribute("version",devinfo.version);
          attributes.setAttribute("password",devinfo.password);
          attributes.setAttribute("username",devinfo.username);
          attributes.setAttribute("channelno",devinfo.channelno);
          attributes.setAttribute("port",devinfo.port);
          attributes.setAttribute("ip",devinfo.ip);
          attributes.setAttribute("type",devinfo.type);
          attributes.setAttribute("name",devinfo.name);
          attributes.setAttribute("id",devinfo.id);
         // QDomNode new_node=attributes.toNotation();

    //查找old_node
    QDomElement root=doc.documentElement();
    QDomNodeList list=root.elementsByTagName("device"); //2行device数据
    QDomNode old_node=list.at(0);                        //id=0的device行

      root.replaceChild(attributes,old_node);

    if(!file.open((QFile::WriteOnly|QFile::Truncate)))
    {
        return;
    }
    QTextStream output_stream(&file);
    doc.save(output_stream,4);
    file.close();
}

修改之前:
在这里插入图片描述修改之后:
QT5——xml文件的读写_第6张图片

你可能感兴趣的:(QT)