2011-02-14 11 views
6

Bir XML dosyasına yaklaşık 20-30 MB (650000 satır) üzerinden döngü yaparken sorun yaşıyorum. Büyük bir XML dosyasının üzerinde döngü

Bu

benim meta kodu: xml dosyasının

<cffile action="READ" ile="file.xml" variable="usersRaw"> 

<cfset usersXML = XmlParse(usersRaw)> 
<cfset advsXML = XmlSearch(usersXML, "/advs/advuser")> 
<cfset users = XmlSearch(usersXML, "/advs/advuser/user")> 

<cfset numUsers = ArrayLen(users)> 
<cfloop index="i" from="1" to="#numUsers#"> 
    ... some selects... 
    ... insert... 
    <cfset advs = annunciXml[i]["vehicle"]> 
    <cfset numAdvs = ArrayLen(advs)> 
    <cfloop index="k" from="1" to="#numAdvs#">   
     ... insert... or ... update... 
    </cfloop> 
</cfloop> 

yapıdır.İlk (evet, değil çok iyi :-)

<advs> 
    <advuser> 
     <user> 
     </user> 
     <vehicle> 
     <vehicle> 
    </advuser> 
</advs> 

~ 120,000 satır sonra bir hata alıyorum: " Bellek yetersiz".

Komut dizimin performansını nasıl artırabilirim?

Maksimum bellek tüketiminin nerede olduğunu nasıl teşhis edebilirim?

cevap

10

@SamG ColdFusion XML ayrıştırma çünkü DOM ayrıştırıcı bunu yapamaz bu doğru yardımcı olacaktır, ancak SAX acı vericidir yerine çok daha basit yineleyici arayüzü sağlayan bir StAX ayrıştırıcı kullanın. See the answer to another question I provided for an example of how to do this with ColdFusion.

Bu, örneğin ne yaparım kabaca geçerli:

<cfset fis = createObject("java", "java.io.FileInputStream").init(
    "#getDirectoryFromPath(getCurrentTemplatePath())#/file.xml" 
)> 
<cfset bis = createObject("java", "java.io.BufferedInputStream").init(fis)> 
<cfset XMLInputFactory = createObject("java", "javax.xml.stream.XMLInputFactory").newInstance()> 
<cfset reader = XMLInputFactory.createXMLStreamReader(bis)> 

<cfloop condition="#reader.hasNext()#"> 
    <cfset event = reader.next()> 
    <cfif event EQ reader.START_ELEMENT> 
     <cfswitch expression="#reader.getLocalName()#"> 
      <cfcase value="advs"> 
       <!--- root node, do nothing ---> 
      </cfcase> 
      <cfcase value="advuser"> 
       <!--- set values used later on for inserts, selects, updates ---> 
      </cfcase> 
      <cfcase value="user"> 
       <!--- some selects and insert ---> 
      </cfcase> 
      <cfcase value="vehicle"> 
       <!--- insert or update ---> 
      </cfcase> 
     </cfswitch> 
    </cfif> 
</cfloop> 

<cfset reader.close()> 
+0

coldfusion bir javascript uyumlu bir ortamdır? –

+0

@ vtd-xml-author: "uyumlu ortam" ile ne demek istediğinizi açıklayın. ColdFusion'ın birincil amacı, HTTP isteklerine yanıt vermek için sunucu tarafı dilidir. Bu şekilde, çıktı genellikle HTML, CSS ve JavaScript'dir. Ve AJAX isteklerine kolayca cevap verebilecek özelliklere de sahiptir. – orangepips

+0

Sadece meraktan dolayı, xml'yi ayrıştırmak için jquery'yi kullanırsanız ve sonuçları veri hattını işleyen bir coldfusion cfc'ye gönderirseniz ne olur? Sadece bir düşünce. – crosenblum

1

Cold Fusion XML Ayrıştırıcısının bu dosya boyutları için uygun olmayan DOM Ayrıştırma'yı kullandığını düşünüyorum. Olay odaklı bir SAX ayrıştırıcısı bulmaya çalışmalısınız. Belki bu linki http://coldfusion.sys-con.com/node/236002

1

Ben ColdFusion bilmiyorum ama 20-30Mb bir bellek içi ağacı oluşturmak teknolojiler için kapsam dışı değildir; Birçok kişi rutin olarak 200Mb dosyalarında XSLT dönüşümlerini çalıştırıyor.

SAX ayrıştırma işlemine geçmek, aşırı bir ölçü gibi sesler çıkarır - bu, düşük düzeyli bir arabirimdir.

2

orangepips makul bir çözüm sunar. Lütfen ColdFusion'da çok büyük XML dosyalarını işlemek için Ben Nadel'in çözümüne bir göz atın. Yaklaşımını 1.2 milyon satırlık bir 50MB XML dosyasına test ettim. Ben, turuncupipslerin burada sağladığı benzer bir yaklaşımı kullanır - Java kullanarak akışını yapın, ardından ColdFusion'daki her düğümü mallara ulaşmak için XMLParse'ı kullanın. Check out - Ben Nadel'in kod ve öğreticiler gibi, sadece çalışır.

http://www.bennadel.com/blog/1345-Ask-Ben-Parsing-Very-Large-XML-Documents-In-ColdFusion.htm

İlgili konular