在平時(shí)工作中,難免會(huì)遇到把xml作為數(shù)據(jù)存儲(chǔ)格式,。面對(duì)目前種類繁多的解決方案,哪個(gè)最適合我們呢,?在這篇文章中,我對(duì)這四種主流方案做一個(gè)不完全評(píng)測(cè),,僅僅針對(duì)遍歷xml這塊來測(cè)試,因?yàn)楸闅vxml是工作中使用最多的(至少我認(rèn)為),。
預(yù)備 測(cè)試環(huán)境: amd毒龍1.4g oc 1.5g、256m ddr333,、windows2000 server sp4、sun jdk 1.4.1+eclipse 2.1+resin 2.1.8,,在debug模式下測(cè)試。 xml文件格式如下: ?。?xml version="1.0" encoding="gb2312"?><result><value> <no>a1234</no> ?。糰ddr>四川省xx縣xx鎮(zhèn)xx路x段xx號(hào)</addr></value><value> <no>b1234</no> ?。糰ddr>四川省xx市xx鄉(xiāng)xx村xx組</addr></value></result> 測(cè)試方法: 采用jsp端調(diào)用bean(至于為什么采用jsp來調(diào)用,請(qǐng)參考:http://blog.csdn.net/rosen/archive/2004/10/15/138324.aspx),,讓每一種方案分別解析10k,、100k,、1000k,、10000k的xml文件,計(jì)算其消耗時(shí)間(單位:毫秒),。 jsp文件: <%@ page contenttype="text/html; charset=gb2312" %><%@ page import="com.test.*"%> ?。糷tml><body><%string args[]={""};myxmlreader.main(args);%></body></html> 測(cè)試 首先出場(chǎng)的是dom(jaxp crimson解析器) dom是用與平臺(tái)和語言無關(guān)的方式表示xml文檔的官方w3c標(biāo)準(zhǔn),。dom是以層次結(jié)構(gòu)組織的節(jié)點(diǎn)或信息片斷的集合。這個(gè)層次結(jié)構(gòu)允許開發(fā)人員在樹中尋找特定信息,。分析該結(jié)構(gòu)通常需要加載整個(gè)文檔和構(gòu)造層次結(jié)構(gòu),然后才能做任何工作,。由于它是基于信息層次的,因而dom被認(rèn)為是基于樹或基于對(duì)象的,。dom以及廣義的基于樹的處理具有幾個(gè)優(yōu)點(diǎn),。首先,,由于樹在內(nèi)存中是持久的,因此可以修改它以便應(yīng)用程序能對(duì)數(shù)據(jù)和結(jié)構(gòu)作出更改,。它還可以在任何時(shí)候在樹中上下導(dǎo)航,,而不是像sax那樣是一次性的處理。dom使用起來也要簡(jiǎn)單得多,。 另一方面,對(duì)于特別大的文檔,,解析和加載整個(gè)文檔可能很慢且很耗資源,,因此使用其他手段來處理這樣的數(shù)據(jù)會(huì)更好,。這些基于事件的模型,,比如sax。 bean文件: package com.test; import java.io.*;import java.util.*;import org.w3c.dom.*;import javax.xml.parsers.*; public class myxmlreader{ public static void main(string arge[]){ long lasting =system.currenttimemillis(); try{ file f=new file("data_10k.xml"); documentbuilderfactory factory=documentbuilderfactory.newinstance(); documentbuilder builder=factory.newdocumentbuilder(); document doc = builder.parse(f); nodelist nl = doc.getelementsbytagname("value"); for (int i=0;i<nl.getlength();i++){ system.out.print("車牌號(hào)碼:" + doc.getelementsbytagname("no").item(i).getfirstchild().getnodevalue()); system.out.println("車主地址:" + doc.getelementsbytagname("addr").item(i).getfirstchild().getnodevalue()); } }catch(exception e){ e.printstacktrace(); } system.out.println("運(yùn)行時(shí)間:"+(system.currenttimemillis() - lasting)+"毫秒");}} 10k消耗時(shí)間:265 203 219 172 100k消耗時(shí)間:9172 9016 8891 9000 1000k消耗時(shí)間:691719 675407 708375 739656 10000k消耗時(shí)間:outofmemoryerror 接著是sax 這種處理的優(yōu)點(diǎn)非常類似于流媒體的優(yōu)點(diǎn),。分析能夠立即開始,,而不是等待所有的數(shù)據(jù)被處理。而且,,由于應(yīng)用程序只是在讀取數(shù)據(jù)時(shí)檢查數(shù)據(jù),,因此不需要將數(shù)據(jù)存儲(chǔ)在內(nèi)存中。這對(duì)于大型文檔來說是個(gè)巨大的優(yōu)點(diǎn),。事實(shí)上,,應(yīng)用程序甚至不必解析整個(gè)文檔;它可以在某個(gè)條件得到滿足時(shí)停止解析,。一般來說,sax還比它的替代者dom快許多,。 選擇dom還是選擇sax? 對(duì)于需要自己編寫代碼來處理xml文檔的開發(fā)人員來說,, 選擇dom還是sax解析模型是一個(gè)非常重要的設(shè)計(jì)決策,。 dom采用建立樹形結(jié)構(gòu)的方式訪問xml文檔,,而sax采用的事件模型,。 dom解析器把xml文檔轉(zhuǎn)化為一個(gè)包含其內(nèi)容的樹,,并可以對(duì)樹進(jìn)行遍歷。用dom解析模型的優(yōu)點(diǎn)是編程容易,,開發(fā)人員只需要調(diào)用建樹的指令,然后利用navigation apis訪問所需的樹節(jié)點(diǎn)來完成任務(wù),??梢院苋菀椎奶砑雍托薷臉渲械脑?。然而由于使用dom解析器的時(shí)候需要處理整個(gè)xml文檔,所以對(duì)性能和內(nèi)存的要求比較高,,尤其是遇到很大的xml文件的時(shí)候。由于它的遍歷能力,,dom解析器常用于xml文檔需要頻繁的改變的服務(wù)中。 sax解析器采用了基于事件的模型,,它在解析xml文檔的時(shí)候可以觸發(fā)一系列的事件,當(dāng)發(fā)現(xiàn)給定的tag的時(shí)候,,它可以激活一個(gè)回調(diào)方法,告訴該方法制定的標(biāo)簽已經(jīng)找到,。sax對(duì)內(nèi)存的要求通常會(huì)比較低,因?yàn)樗岄_發(fā)人員自己來決定所要處理的tag,。特別是當(dāng)開發(fā)人員只需要處理文檔中所包含的部分?jǐn)?shù)據(jù)時(shí),,sax這種擴(kuò)展能力得到了更好的體現(xiàn)。但用sax解析器的時(shí)候編碼工作會(huì)比較困難,,而且很難同時(shí)訪問同一個(gè)文檔中的多處不同數(shù)據(jù)。 bean文件: package com.test;import org.xml.sax.*;import org.xml.sax.helpers.*;import javax.xml.parsers.*; public class myxmlreader extends defaulthandler { java.util.stack tags = new java.util.stack(); public myxmlreader() { super();} public static void main(string args[]) { long lasting = system.currenttimemillis(); try { saxparserfactory sf = saxparserfactory.newinstance(); saxparser sp = sf.newsaxparser(); myxmlreader reader = new myxmlreader(); sp.parse(new inputsource("data_10k.xml"), reader); } catch (exception e) { e.printstacktrace(); } system.out.println("運(yùn)行時(shí)間:" + (system.currenttimemillis() - lasting) + "毫秒");} public void characters(char ch[], int start, int length) throws saxexception { string tag = (string) tags.peek(); if (tag.equals("no")) { system.out.print("車牌號(hào)碼:" + new string(ch, start, length));}if (tag.equals("addr")) { system.out.println("地址:" + new string(ch, start, length));}} public void startelement(string uri,string localname,string qname,attributes attrs) { tags.push(qname);}} 10k消耗時(shí)間:110 47 109 78 100k消耗時(shí)間:344 406 375 422 1000k消耗時(shí)間:3234 3281 3688 3312 10000k消耗時(shí)間:32578 34313 31797 31890 30328 然后是jdom http://www./ jdom的目的是成為java特定文檔模型,,它簡(jiǎn)化與xml的交互并且比使用dom實(shí)現(xiàn)更快。由于是第一個(gè)java特定模型,,jdom一直得到大力推廣和促進(jìn)。正在考慮通過“java規(guī)范請(qǐng)求jsr-102”將它最終用作“java標(biāo)準(zhǔn)擴(kuò)展”,。從2000年初就已經(jīng)開始了jdom開發(fā)。 jdom與dom主要有兩方面不同,。首先,jdom僅使用具體類而不使用接口,。這在某些方面簡(jiǎn)化了api,,但是也限制了靈活性,。第二,api大量使用了collections類,,簡(jiǎn)化了那些已經(jīng)熟悉這些類的java開發(fā)者的使用。 jdom文檔聲明其目的是“使用20%(或更少)的精力解決80%(或更多)java/xml問題”(根據(jù)學(xué)習(xí)曲線假定為20%),。jdom對(duì)于大多數(shù)java/xml應(yīng)用程序來說當(dāng)然是有用的,,并且大多數(shù)開發(fā)者發(fā)現(xiàn)api比dom容易理解得多,。jdom還包括對(duì)程序行為的相當(dāng)廣泛檢查以防止用戶做任何在xml中無意義的事,。然而,它仍需要您充分理解xml以便做一些超出基本的工作(或者甚至理解某些情況下的錯(cuò)誤),。這也許是比學(xué)習(xí)dom或jdom接口都更有意義的工作。 jdom自身不包含解析器,。它通常使用sax2解析器來解析和驗(yàn)證輸入xml文檔(盡管它還可以將以前構(gòu)造的dom表示作為輸入)。它包含一些轉(zhuǎn)換器以將jdom表示輸出成sax2事件流,、dom模型或xml文本文檔。jdom是在apache許可證變體下發(fā)布的開放源碼,。 bean文件: package com.test; import java.io.*;import java.util.*;import org.jdom.*;import org.jdom.input.*; public class myxmlreader { public static void main(string arge[]) { long lasting = system.currenttimemillis(); try { saxbuilder builder = new saxbuilder(); document doc = builder.build(new file("data_10k.xml")); element foo = doc.getrootelement(); list allchildren = foo.getchildren(); for(int i=0;i<allchildren.size();i++) { system.out.print("車牌號(hào)碼:" + ((element)allchildren.get(i)).getchild("no").gettext()); system.out.println("車主地址:" + ((element)allchildren.get(i)).getchild("addr").gettext()); } } catch (exception e) { e.printstacktrace(); } system.out.println("運(yùn)行時(shí)間:" + (system.currenttimemillis() - lasting) + "毫秒");}} 10k消耗時(shí)間:125 62 187 94 100k消耗時(shí)間:704 625 640 766 1000k消耗時(shí)間:27984 30750 27859 30656 10000k消耗時(shí)間:outofmemoryerror 最后是dom4j http://dom4j./ 雖然dom4j代表了完全獨(dú)立的開發(fā)結(jié)果,,但最初,,它是jdom的一種智能分支。它合并了許多超出基本xml文檔表示的功能,,包括集成的xpath支持、xml schema支持以及用于大文檔或流化文檔的基于事件的處理,。它還提供了構(gòu)建文檔表示的選項(xiàng),它通過dom4j api和標(biāo)準(zhǔn)dom接口具有并行訪問功能,。從2000下半年開始,它就一直處于開發(fā)之中,。 為支持所有這些功能,dom4j使用接口和抽象基本類方法,。dom4j大量使用了api中的collections類,但是在許多情況下,,它還提供一些替代方法以允許更好的性能或更直接的編碼方法,。直接好處是,,雖然dom4j付出了更復(fù)雜的api的代價(jià),,但是它提供了比jdom大得多的靈活性,。 在添加靈活性,、xpath集成和對(duì)大文檔處理的目標(biāo)時(shí),dom4j的目標(biāo)與jdom是一樣的:針對(duì)java開發(fā)者的易用性和直觀操作,。它還致力于成為比jdom更完整的解決方案,,實(shí)現(xiàn)在本質(zhì)上處理所有java/xml問題的目標(biāo),。在完成該目標(biāo)時(shí),它比jdom更少?gòu)?qiáng)調(diào)防止不正確的應(yīng)用程序行為,。 dom4j是一個(gè)非常非常優(yōu)秀的java xml api,具有性能優(yōu)異,、功能強(qiáng)大和極端易用使用的特點(diǎn),同時(shí)它也是一個(gè)開放源代碼的軟件,。如今你可以看到越來越多的java軟件都在使用dom4j來讀寫xml,特別值得一提的是連sun的jaxm也在用dom4j,。 bean文件: package com.test; import java.io.*;import java.util.*;import org.dom4j.*;import org.dom4j.io.*; public class myxmlreader { public static void main(string arge[]) { long lasting = system.currenttimemillis(); try { file f = new file("data_10k.xml"); saxreader reader = new saxreader(); document doc = reader.read(f); element root = doc.getrootelement(); element foo; for (iterator i = root.elementiterator("value"); i.hasnext();) { foo = (element) i.next(); system.out.print("車牌號(hào)碼:" + foo.elementtext("no")); system.out.println("車主地址:" + foo.elementtext("addr")); } } catch (exception e) { e.printstacktrace(); } system.out.println("運(yùn)行時(shí)間:" + (system.currenttimemillis() - lasting) + "毫秒");}} 10k消耗時(shí)間:109 78 109 31 100k消耗時(shí)間:297 359 172 312 1000k消耗時(shí)間:2281 2359 2344 2469 10000k消耗時(shí)間:20938 19922 20031 21078 jdom和dom在性能測(cè)試時(shí)表現(xiàn)不佳,,在測(cè)試10m文檔時(shí)內(nèi)存溢出。在小文檔情況下還值得考慮使用dom和jdom,。雖然jdom的開發(fā)者已經(jīng)說明他們期望在正式發(fā)行版前專注性能問題,但是從性能觀點(diǎn)來看,,它確實(shí)沒有值得推薦之處,。另外,,dom仍是一個(gè)非常好的選擇。dom實(shí)現(xiàn)廣泛應(yīng)用于多種編程語言,。它還是許多其它與xml相關(guān)的標(biāo)準(zhǔn)的基礎(chǔ),因?yàn)樗将@得w3c推薦(與基于非標(biāo)準(zhǔn)的java模型相對(duì)),,所以在某些類型的項(xiàng)目中可能也需要它(如在javascript中使用dom),。 sax表現(xiàn)較好,,這要依賴于它特定的解析方式,。一個(gè)sax檢測(cè)即將到來的xml流,,但并沒有載入到內(nèi)存(當(dāng)然當(dāng)xml流被讀入時(shí),,會(huì)有部分文檔暫時(shí)隱藏在內(nèi)存中)。 無疑,,dom4j是這場(chǎng)測(cè)試的獲勝者,,目前許多開源項(xiàng)目中大量采用dom4j,,例如大名鼎鼎的hibernate也用dom4j來讀取xml配置文件,。如果不考慮可移植性,那就采用dom4j吧,!(文/rosen) 文章整理:站長(zhǎng)天空 網(wǎng)址:http://www./ 以上信息與文章正文是不可分割的一部分,如果您要轉(zhuǎn)載本文章,請(qǐng)保留以上信息,謝謝! |
|