【问题标题】:Looping over a large XML file循环一个大的 XML 文件
【发布时间】:2011-02-14 17:32:48
【问题描述】:

我在循环一个大约 20-30 MB(650000 行)的 XML 文件时遇到问题。

这是我的元代码:

<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>

xml 文件的结构是(是的,不是很好:-)

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

大约 120,000 行后,我收到一个错误:“内存不足”。

如何提高脚本的性能?

如何诊断最大内存消耗在哪里?

【问题讨论】:

    标签: xml coldfusion


    【解决方案1】:

    @SamG 是正确的,ColdFusion XML 解析由于 DOM 解析器而无法做到,但是 SAX 很痛苦,而是使用 StAX 解析器,它提供了更简单的迭代器接口。 See the answer to another question I provided for an example of how to do this with ColdFusion.

    这大致就是您为示例所做的:

    <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()>
    

    【讨论】:

    • coldfusion 是 javascript 兼容的环境吗?
    • @vtd-xml-author:解释一下“兼容环境”是什么意思。 ColdFusion 的主要用途是用于响应 HTTP 请求的服务器端语言。因此,它的输出通常是 HTML、CSS 和 JavaScript。而且,它具有轻松响应 AJAX 请求的功能。
    • 只是出于好奇,如果您使用 jquery 解析 xml,然后将结果发送给 Coldfusion cfc,后者将逐行处理数据。只是一个想法。
    • 没有尝试过,但相信 JavaScript(以及扩展 jquery)也创建了一个 DOM 表示,因此最终可能也会受到内存限制。
    【解决方案2】:

    orangepips 提供了一个合理的解决方案。请查看 Ben Nadel 在 ColdFusion 中处理非常大的 XML 文件的解决方案。我已经在一个包含 120 万行的 50MB XML 文件上测试了他的方法。 Ben 使用了 orangepips 在此处提供的类似方法——使用 Java 对其进行流式传输,然后在 ColdFusion 中对每个节点进行 XMLParse 以获取货物。看看吧——就像 Ben Nadel 的大多数代码和教程一样,它确实有效。

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

    【讨论】:

      【解决方案3】:

      我相信 Cold Fusion XML Parser 使用 DOM Parsing,它不适合这种文件大小。您应该尝试找到一个 SAX 解析器,它是事件驱动的。也许这个链接会有所帮助 http://coldfusion.sys-con.com/node/236002

      【讨论】:

        【解决方案4】:

        我不知道 ColdFusion,但 20-30Mb 并没有超出构建内存树的技术的范围;许多人经常对 200Mb 的文件运行 XSLT 转换。

        转向 SAX 解析听起来像是一种极端的措施 - 它是一个低级接口。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-07-23
          • 1970-01-01
          • 2012-03-16
          • 1970-01-01
          • 2013-07-21
          • 1970-01-01
          • 2013-10-24
          相关资源
          最近更新 更多