大家好,又见面了,我是你们的朋友全栈君。
一直以来,在代码没有任何限制的使用XML编解码情况下,服务器代码性能会非常低下。
要提高服务器性能:
一种方案是优化原有架构,只在对外接口及考虑后期可能扩展的接口使用XML编解码,在内部处理尽量使用二进制(结构体)编码,效率会大大提升。这个原因不用解释也很清楚,效率低下的字符串匹配变为二进制匹配,效率提升哪绝对是可观的!!!
还有一种方案,不改变原有架构(很可能模块很多,代码逻辑复杂,重新将原来的XML转换为二进制,代码修改量大),替换原来的XML解析库,提高XML解析效率。这种绝对没有第一种效率提升高,但如果选好库,提升有时也很大。
XML解析库当然不用自己去写了,借鉴前辈大能们的写的经过战火考验的开源库是最好的办法。
分析现有的开源XML库,大家比较常用的是TINYxml,小巧灵活,效率也不差。最近在查找资料是发现有一种和RAPIDjson对应的RAPIDxml解析库,号称效率是TINYxml的十几倍到几十倍,很多用过的兄弟都在大力推荐。
写了个测试代码试用了一下,发现确实不错,编译很方便,没什么需要特别注意的,编码使用和TINYxml相似,但更简单。不过比TINYxml使用上技术“难度”要大一些–这是因为RAPIDxml为了提高解析速度,不会重新复制XML字符串,都是直接在原字符串上解析并修改,如果对指针、内存理解不深,使用不准确很可能会引起解析或者内存异常,程序崩溃。
下面附简单的使用举例:
//文件包含
#include “....3rdincluderapidxmlrapidxml.hpp” #include “....3rdincluderapidxmlrapidxml_print.hpp” #include “....3rdincluderapidxmlrapidxml_iterators.hpp” #include “....3rdincluderapidxmlrapidxml_utils.hpp” using namespace rapidxml;
void test_rapidxml_create() { //创建测试 xml_document<wchar_t> doc; //析构时会自动释放内存,allocate_node相关会自动在对象析构时释放整个pool内存 xml_node<wchar_t>* rot = doc.allocate_node(rapidxml::node_pi,doc.allocate_string(L”xml version=’1.0′ encoding=’utf-8′”)); //xml_node<wchar_t>* rot = doc.allocate_node(rapidxml::node_pi, L”xml version=’1.0′ encoding=’utf-8′”); //不能这样用,内部用到的临时字符串在xml分配时只会复制指针,不会申请内存 doc.append_node(rot); xml_node<wchar_t>* node = doc.allocate_node(node_element, doc.allocate_string(L”text”), NULL); xml_node<wchar_t>* row = doc.allocate_node(node_element, doc.allocate_string(L”row”), doc.allocate_string(L”3″)); doc.append_node(node); node->append_node(row);
xml_node<wchar_t>* row0 = doc.allocate_node(node_element, doc.allocate_string(L”row_0″), NULL); xml_node<wchar_t>* row1 = doc.allocate_node(node_element, doc.allocate_string(L”row_1″), NULL); xml_node<wchar_t>* row2 = doc.allocate_node(node_element, doc.allocate_string(L”row_2″), NULL); row->append_node(row0); row->append_node(row1); row->append_node(row2);
row0->append_node(doc.allocate_node(node_element, doc.allocate_string(L”name”), doc.allocate_string(L”wang”))); row0->append_node(doc.allocate_node(node_element, doc.allocate_string(L”tel”), doc.allocate_string(L”133xxxx”))); row0->append_node(doc.allocate_node(node_element, doc.allocate_string(L”住址”), doc.allocate_string(L”北 京”)));
row1->append_node(doc.allocate_node(node_element, doc.allocate_string(L”name”), doc.allocate_string(L”li”))); row1->append_node(doc.allocate_node(node_element, doc.allocate_string(L”tel”), doc.allocate_string(L”135xxxx”))); row1->append_node(doc.allocate_node(node_element, doc.allocate_string(L”住址”), doc.allocate_string(L”西 安?”)));
row2->append_node(doc.allocate_node(node_element, doc.allocate_string(L”name”), doc.allocate_string(L”zhang”))); row2->append_node(doc.allocate_node(node_element, doc.allocate_string(L”tel”), doc.allocate_string(L”137xxxx”))); row2->append_node(doc.allocate_node(node_element, doc.allocate_string(L”住址”), doc.allocate_string(L”太 原2#”)));
std::wstring sOut; rapidxml::print(std::back_inserter(sOut), doc, 0); wprintf(L”n===========================ntest xml create doc:n%sn”, sOut.c_str()); }
void test_rapidxml_error() { //#define RAPIDXML_NO_EXCEPTIONS //异常测试 xml_document<wchar_t> doc;
//doc.parse<0>(L”<text>111</text>”);//临时变量内存释放的异常不是xml解析异常,是windows内存访问异常 try { wchar_t strXml[] = L”<text><row>”; doc.parse<0>(strXml);//会改变参数的内容,strXml的生命周期必须到解析完 } catch (rapidxml::parse_error &e) { //wchar_t *pErr = e.where(); //模版类型老处理不好Ch printf(“n===========================ntest xml ERROR:what-%sn”, e.what()); //what是char类型 //wprintf(L”ERROR:%sn”, pErr); return ; } }
void test_rapidxml_prase() { std::wstring strRow; std::wstring strName; std::wstring strTel; std::wstring strAddr; std::wstring strTemp;
//解析测试 wprintf(L”n===========================ntest xml prase:n”);
rapidxml::xml_document<wchar_t> doc;
wchar_t strXml[] = L”<text><row>3</row><row_0><name>wang</name><tel>133xxxx</tel><住址>开北 京</住址></row_0><row_1><name>li</name><tel>135xxxx</tel><住址>西 安?</住址></row_1><row_2><name>zhang</name><tel>137xxxx</tel><住址>太 原2#</住址></row_2></text>”; //wchar_t strXml[] = L”<住址>北 京</住址>”; doc.parse<0>(strXml); //不重新申请内存,会改变参数内容,所以必须使用在解析阶段可用的内存使用 rapidxml::xml_node<wchar_t> * node = doc.first_node(L”text”);
if (node) { node = node->first_node(L”row”); //安全使用时可以判断一下返回的node指针是否为空
if (node) { strTemp = node->value(); } } int iRow = _wtoi(strTemp.c_str());
wprintf(L”ROW:%dn”, iRow);
rapidxml::xml_node<wchar_t> * node_row = NULL; for(int i = 0; i < iRow; i ) { strRow = stringformat(L”row_%d”, i); node_row = doc.first_node(L”text”); if (node_row) { node_row = node_row->first_node(strRow.c_str()); strName = node_row->first_node(L”name”)->value(); strTel = node_row->first_node(L”tel”)->value(); strAddr = node_row->first_node(L”住址”)->value(); } wprintf(L”ROW_index:%d[name:%s;tel:%s;住址:%s]n”, i, strName.c_str(), strTel.c_str(), strAddr.c_str()); }
//打印输出 std::wstring sOut; print(std::back_inserter(sOut), doc, 0); wprintf(L”doc1:%sn”, sOut.c_str());
wchar_t cbOut[1024] = {0}; print(cbOut, doc, 0); wprintf(L”doc2:%sn”, cbOut);
//std::cout << doc;
//print(std::cout, doc, 0); }
void test_rapidxml_prase_file_w(char * fileName) { //解析测试 wprintf(L”n===========================ntest xml prase file:n”); std::string strFileName = “c:\test.xml”;
if (fileName) { strFileName = fileName; } rapidxml::file<wchar_t> fdoc(strFileName.c_str()); //注意:这里的文件basic_ifstream不支持UTF-16/UNICODE格式,这种文件格式所有字符都使用双字存储,存储空间较大 //只所以不支持UNICODE格式的是因为,文件读入时以二进制读入,一个ansi字符已经被写成0x0031的占用两个字节的16进制,中间加了0;如果再以wchar格式存储,会变为0x0031 0x0000的样子,后面字符串解析出错;而如果以char读入,由于xmlfile中char向量的存储,后面释放内存会出错 rapidxml::xml_document<wchar_t> doc;
wchar_t *strContent = (wchar_t *)fdoc.data(); doc.parse<0>(strContent);//不重新申请内存,会改变参数内容,所以必须使用在解析阶段可用的内存使用
printf(“parse file ok:%sn”, strFileName.c_str()); rapidxml::xml_node<wchar_t> * node = doc.first_node(); if (node) { wprintf(L”node:[name:%s]%sn”, node->name(), node->value()); }
//打印输出 std::wstring sOut; print(std::back_inserter(sOut), doc, 0); //wprintf(L”doc1:%sn”, sOut.c_str()); //debug }
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/160870.html原文链接:https://javaforall.cn