﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-梦想的天堂</title><link>http://www.cppblog.com/sunnyshaw/</link><description /><language>zh-cn</language><lastBuildDate>Sat, 04 Apr 2026 05:40:01 GMT</lastBuildDate><pubDate>Sat, 04 Apr 2026 05:40:01 GMT</pubDate><ttl>60</ttl><item><title>XML字符串解析介绍</title><link>http://www.cppblog.com/sunnyshaw/archive/2007/06/17/26522.html</link><dc:creator>IT民工</dc:creator><author>IT民工</author><pubDate>Sun, 17 Jun 2007 15:02:00 GMT</pubDate><guid>http://www.cppblog.com/sunnyshaw/archive/2007/06/17/26522.html</guid><wfw:comment>http://www.cppblog.com/sunnyshaw/comments/26522.html</wfw:comment><comments>http://www.cppblog.com/sunnyshaw/archive/2007/06/17/26522.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/sunnyshaw/comments/commentRss/26522.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sunnyshaw/services/trackbacks/26522.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前些天在做一个小项目，需要实现从字符串到XML文件的逆向转换过程。该字符串由XML文件所得。由于使用环境对解析时间和内存使用量有严格的要求，因此必须确保解析速度和所占用内存。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面简单叙述一下我的实现过程。最开始采用的方法是每次从文件字符串里面读入一个节点的值，具体读取过程有xml文件各个节点属性决定。再利用一个stack对xml文件节点进行管理。大致思路是每读入一个字符串，先判断其类型，如果是Element或者text, comment, cdata类型则入栈，若为EndElement则出栈，这样就可以顺利建立起各个父子节点之间的关系。<br>&nbsp;&nbsp;&nbsp;&nbsp; 采用这样的方法是思路比较的明确，实现起来比较的简单，缺点是解析速度太慢了，解析一个2M左右的XML文件要10多分钟，而且所费时间与文件的大小成几何级别增长，根本不可能接受。在采用这种方法过程中，也出现了一个小插曲。就是在解析比较大的xml文件时，当解析的xml节点超过1500个时，就会导致内存分配错误，堆栈溢出，开始是百思不得其解，后来才知道是由于我在解析字符串过程中，采用了递归的方法，因此内存消耗很厉害，特别是我开始传入一个const字符串时，一个小小的几百K(以200k为例)的文件就可能导致内存一下子消耗几百M，因为每次只读入一个节点字符串，这样最终大小可以达到200K+19.96k+....+0 ~=200*(200-1)k/2~ = 200M.因此导致编译器堆栈溢出，解决方法有几种，一是将堆栈设置大些，另外就是改递归为循环。我采用了后者。<br>&nbsp;&nbsp;&nbsp;&nbsp; 在进行字符串解析时，我大量采用了STL的字符串find,find_first_of()，substr等</p>
<p>函数，但是这通常只在搜索小字符串时速度较快，在长达几M的字符串时，由于大块的内存操作，程序运行慢如蜗牛。而且我在前面的实现方法中，每次是提取一个节点，然后再进行解析，这样在读取和解析过程中，会导致许多重复的步骤，严重影响工作效率。 于是我就采用一个了for循环对读入的一个个字节进行处理，这样速度得到显著的提高。但是程序在解析大字符串时还是运行很慢，我开始 意识到是长字符串的问题，因此得想方法分段解析才行。于是决定每次从字符串里面提取一定的字符处理。在解析长达几M的字符串时，我先后试验了每次提取64bit，128bit，256bit,512bit, 1k, 2k, 4k等不同长度的字符串，发现在处理大字符串时，4K的效果最好。在解析一个8M左右的xml字符串时，速度可以达到30S，但是内存消耗有点厉害了，达100M。因此也很难满足要求。<br>&nbsp;&nbsp;&nbsp;&nbsp; 最后还是采用了一种比较折中的方法，就是在初次解析时，只解析根节点以及其下一层子节点，在保存过程中再分段解析，主要可以极大的减少内存消耗，8M左右的文件可以降低到20M左右内存。速度也有所提高,最终耗时3s左右。<br></p>
<img src ="http://www.cppblog.com/sunnyshaw/aggbug/26522.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sunnyshaw/" target="_blank">IT民工</a> 2007-06-17 23:02 <a href="http://www.cppblog.com/sunnyshaw/archive/2007/06/17/26522.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erase method in STL</title><link>http://www.cppblog.com/sunnyshaw/archive/2007/05/03/23374.html</link><dc:creator>IT民工</dc:creator><author>IT民工</author><pubDate>Thu, 03 May 2007 09:22:00 GMT</pubDate><guid>http://www.cppblog.com/sunnyshaw/archive/2007/05/03/23374.html</guid><wfw:comment>http://www.cppblog.com/sunnyshaw/comments/23374.html</wfw:comment><comments>http://www.cppblog.com/sunnyshaw/archive/2007/05/03/23374.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/sunnyshaw/comments/commentRss/23374.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sunnyshaw/services/trackbacks/23374.html</trackback:ping><description><![CDATA[&nbsp;In these days, I used STL in a project, and met several problems. One was caused by erase method. As we know, when we delete a&nbsp;element&nbsp;in a container in STL, the iterator itself will be changed, so the the iterator should be set correctly. A right method can be used as following:<br>&nbsp;&nbsp;&nbsp;Typedef&nbsp; list&lt;MyClass*&gt;::Iterator myIter;<br>&nbsp;&nbsp;&nbsp;for(myIter it = listObj.begin(); it != listObj.end();)<br>&nbsp;&nbsp;&nbsp;&nbsp;if(true)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it =&nbsp;listObj.erase(it);<br>&nbsp;&nbsp;&nbsp;else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++it;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<img src ="http://www.cppblog.com/sunnyshaw/aggbug/23374.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sunnyshaw/" target="_blank">IT民工</a> 2007-05-03 17:22 <a href="http://www.cppblog.com/sunnyshaw/archive/2007/05/03/23374.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XmlLite使用简单介绍</title><link>http://www.cppblog.com/sunnyshaw/archive/2007/05/03/Sunnyshaw.html</link><dc:creator>IT民工</dc:creator><author>IT民工</author><pubDate>Thu, 03 May 2007 07:37:00 GMT</pubDate><guid>http://www.cppblog.com/sunnyshaw/archive/2007/05/03/Sunnyshaw.html</guid><wfw:comment>http://www.cppblog.com/sunnyshaw/comments/23372.html</wfw:comment><comments>http://www.cppblog.com/sunnyshaw/archive/2007/05/03/Sunnyshaw.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/sunnyshaw/comments/commentRss/23372.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sunnyshaw/services/trackbacks/23372.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最近因为项目的需要，将一个应用软件的底层XML处理模块进行重写，由MSDOM改用xmlLite来完成。XmlLite是微软专门针对C++使用者开发的一个轻量级开发包，只具备基本的I/O功能。提供了IXmlReader, IXmlWriter对XML文件进行简单的读写操作。原理很简单，在读一个文件时，循环读取各个节点，然后根据不同的节点类型读取其相关属性数据等。XMLLite中的数据类型主要封装在XmlNodeType中，常使用到的有XmlNodeType_None, XmlNodeType_Element,XmlNodeType_EndElement等。在写数据时，主要根据不同的节点类型，调用相关的API来完成。值得注意的是，由于XMLLite只提供顺序化写的功能，因此在写具有多个深度的节点类型时，需要控制好WriteEndElement()函数的出现顺序等，所以这些都可以通过函数的递归来完成。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于XmlLite只提供简单的读写等功能，因此，在实际应用中，需要对XMLLite提供的功能进行一定的封装，从而提供自己的API功能。下面简单说说我们采用的思路。在读Xml文件时，需要在加载过程建立XML文件的内部数据结构。这可以通过两种方式来完成，一种是在一个循环或者递归过程中，将整个ＸＭＬｌｏａｄ进来；另外一种方法是一次只加载一层节点，然后递归加载其子节点。前面一种方法是在处理大XML文件时，可能会有memory footprint问题。所以最终采用了后面的方法。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在实现过程中，我们采用了composite模式来组织XML文件树结构。通过使用list来建立树结构。全部操作封装在一个类中。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有关相关原因，xmlLite的具体封装实现方法就不提及了。开发过程中，遇到的主要难点是数据的读写和保存，关键是数据结构的处理，其他部分都比较容易。<br>&nbsp;&nbsp;&nbsp;&nbsp; 这我开通blog后的第一篇文章，呵呵，也不知道怎么写好。以后会尽力写好点^_^.
<img src ="http://www.cppblog.com/sunnyshaw/aggbug/23372.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sunnyshaw/" target="_blank">IT民工</a> 2007-05-03 15:37 <a href="http://www.cppblog.com/sunnyshaw/archive/2007/05/03/Sunnyshaw.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>