在.NET CF下保存和读取XML文件数据不是一般的慢……

测试机器规格:
CPU:           TI OMAP 200MHz
FreeMem:   大约 7.5M
WinCE ver: 4.20(build 0)
.NET CF:    1.0

对一个格式大致为(保护公司机密,所以名称和结果不是很真实)

的XML文件用XmlDocument直接进行读取,我的实测结果是:
None.gif < Root >
None.gif  
< Item  attr  = "something" >
None.gif     
< ID > 1 </ ID >
None.gif     
< Name > abcdef </ Name >
None.gif     
< Something  ref  = "alpha"  type  = "beta" > abcdefg </ Something >
None.gif     
< Other  type  = "abc" > 1 </ Other >
None.gif     
< Extension  type  = "linkSame" > Parent </ Extension >
None.gif     
< Parent  xxx  = "yyy" > 3 </ Parent >
None.gif  
</ Item >
None.gif  dot.gif
None.gif
</ Root >
None.gif

当Item数量为150个左右的时候,读取所有信息需要时间大约为6-9秒。当数量为300左右时(此时文件大小大约为110k),时间大约需要11-14秒。当数量暴增到接近6000的时候(大小约为2M),时间需要大约200秒。在桌面下,我们可以轻松的使用XML来进行非结果化数据的存储,但是到了CE平台下面,我们就不能够继续这么干了,至少大量数据这么做是不行的。当然,XML也从来不是为了存储和检索大量数据而设计的,大家主要还是利用XML相对来说非常强大和灵活的描述能力来对一些非结构化的信息进行描述。虽然说6000项数据相对于大型数据库动辄上百万的级别来说还是芝麻绿豆,并且在桌面上也完全能够胜任(大概1.1秒),但对于SmartPhone这种资源较为有限的机器来说就是一个大规模级别的物体了。而非常不幸的是,.NET CF 1.0在这方面的设计也比较糟糕(据传说在2.0会有较大的改进),这两个条件的共同作用造就了上面那个非常糟糕的测试结果。这仅仅是把数据读进内存当中,还没有进行任何的处理,如果让用户去等待这么长的时间去读数据,估计用户肯定得把手机扔掉。

不过这不代表着没有任何改善的余地,比如说,我们可以把文件内容分割。前提条件是实际上不需要所有的内容,并且内容能够有效地分割(包括容易管理)。这个方法的好处是,仍然可以用XML来进行存储。有好处当然也有坏处:需要将内容分割,意味着你需要管理这些分割的部分,比如在程序需要的时候必须能够调度到内存当中,同时检索的难度也加大了(可能需要一个额外的索引文件或者机制来完成)。

在进行这样的分割之前,最好考虑一下是否有其他的解决方案,比如说XmlReader。说起来好像有点复杂,似乎要自己手动处理Xml文件,其实并没有那么复杂,比如下面的这个函数可以用来定位某一个指定的element:
None.gif          //  Seek a specified element node.
None.gif        
//  true: The specified element was found.
None.gif        
//  false: reached the end of file
None.gif
         bool  SeekElement(XmlReader reader,  string  name)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
while(reader.Read())
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (reader.NodeType == XmlNodeType.Element && reader.Name == name)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
return true;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
return false;
ExpandedBlockEnd.gif        }

None.gif

当然了,相对于一句doc.Load(path)来说,还是会复杂不少。此外xml文件内容的结果复杂度也需要简化,这样才便于手动处理。好在我们也不指望在手机上做什么特别复杂的应用,比如说什么内容排版之类的,一般来说数据也不是很复杂。如果你同意我的说法,那么也许可以参考一下我写的代码:

None.gif          void  Travel(XmlReader reader)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif
InBlock.gif            
while (SeekElement(reader, "Item"))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (reader.IsEmptyElement == false)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    FillAttributes(reader);
InBlock.gif                    
while (SeekElementWithEndCheck(reader, "Item") )
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        FillAttribute(reader);
InBlock.gif                        
if (reader.IsEmptyElement == false)
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            
if (SeekTextWithEndCheck(reader, property))
ExpandedSubBlockStart.gifContractedSubBlock.gif                            
dot.gif{
InBlock.gif                                text 
= reader.Value;
InBlock.gif                                MoveToEnd(property);
ExpandedSubBlockEnd.gif                            }
 // end if Text found
ExpandedSubBlockEnd.gif
                        }
 // end if Item is not empty
ExpandedSubBlockEnd.gif
                    }
 // end while find elements under "Item" element
ExpandedSubBlockEnd.gif
                }
 // end if element "Item" is empty
ExpandedSubBlockEnd.gif
            }
 // end while seeking all "Item" elements
ExpandedBlockEnd.gif
        }

None.gif
None.gif        
//  Seek a specified element node.
None.gif        
//  true: The specified element was found.
None.gif        
//  false: reached the end of file
None.gif
         bool  SeekElement(XmlReader reader,  string  name)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
while(reader.Read())
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (reader.NodeType == XmlNodeType.Element && reader.Name == name)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
return true;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
return false;
ExpandedBlockEnd.gif        }

None.gif
None.gif        
//  Seek an element with checking the end of a specified element node
None.gif        
//  true: an element found(the name of element can be retrieve from reader.Name, etc.)
None.gif        
//  false: reached the end of file, or reached the *end element* node "</name>"
None.gif
         bool  SeekElementWithEndCheck(XmlReader reader,  string  name)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
while(reader.Read())
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
switch(reader.NodeType)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
case XmlNodeType.EndElement:
InBlock.gif                        
if (reader.Name == name)
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            
return false;
ExpandedSubBlockEnd.gif                        }

InBlock.gif                        
break;
InBlock.gif                    
case XmlNodeType.Element:
InBlock.gif                        
return true;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
return false;
ExpandedBlockEnd.gif        }

None.gif
None.gif        
//  Seek text within the bound of element *name*
None.gif        
//  true: text found (in reader.Value)
None.gif        
//  false: reached the end of file, or reached the </name> node.
None.gif
         bool  SeekTextWithEndCheck(XmlReader reader,  string  name)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
while(reader.Read())
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
switch(reader.NodeType)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
case XmlNodeType.EndElement:
InBlock.gif                        
if (reader.Name == name)
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            
return false;
ExpandedSubBlockEnd.gif                        }

InBlock.gif                        
break;
InBlock.gif                    
case XmlNodeType.Text:
InBlock.gif                        
return true;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
return false;
ExpandedBlockEnd.gif        }

None.gif
None.gif        
//  travel all the attributes
None.gif
         void  FillAttribute(XmlReader reader)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
if (reader.MoveToFirstAttribute())
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
do
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
// fill your code here
InBlock.gif
                    Console.WriteLine(reader.Name + " : \t" + reader.Value);
ExpandedSubBlockEnd.gif                }
while(reader.MoveToNextAttribute());
ExpandedSubBlockEnd.gif            }

ExpandedBlockEnd.gif        }

None.gif


待续……
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值