2

我需要从一个巨大的(大约 500mb)文件中提取 XML,但我有一个 32 位 JVM,它总是用完堆空间。

我已经编写了一个程序来从这个文件中提取 XML,但是必须读取整个文件(我不能每次迭代使用 100 行左右,因为我不能确保第 100 行是结束XML)。

那么我该怎么做呢?

我的提取程序:

private static ArrayList<String> extractXml(String xml) {
    String[] newXml = xml.split("\\<\\?");
    ArrayList<String> xmlList = new ArrayList<String>(Arrays.asList(newXml));
    for(int i = 0; i<xmlList.size();i++){
        if(!xmlList.get(i).contains("xml version=\"1.0\" encoding=\"UTF-8\"")){
            xmlList.remove(i);
        }
    }
    int size = xmlList.size();
    if(xml.contains("#"))
    for(int j = 0;j<size;j++){
        xmlList.set(j, "<?"+xmlList.get(j));
        xmlList.set(j,xmlList.get(j).split("\\#")[0]);

    }else
        for(int j = 0;j<size;j++){
            xmlList.set(j, "<?"+xmlList.get(j).trim());
            System.out.println(xmlList.get(j));             
        }



    return xmlList;

}

XML 也有一个 Header(它是一个 JMSStream 标头。就像 XML 上的一个包装器),我已经使用上述逻辑成功地删除了它。

示例文件内容:

#---------- #2 : ID:QADC1_HGR1-EMS13112.15DB4FBEA3665328B:4985 ----------#
<MSG_INFO>
    <message type="TextMessage" messageSelector="" receiveTime="2012-09-12T14:37:26.717" jmsServerTimestamp="2012-09-12T14:37:26.775">
        <header JMSMessageID="ID:QADC1_HGR1-EMS13112.15DB4FBEA3665328B:4985" JMSDestination="OPS.FPES.OUTBOUND.FLIGHT.TRACK_A.DISTRIBUTION" JMSDestinationType="Topic" JMSDeliveryMode="2" JMSPriority="4" JMSTimestamp="1347478646775"/>
        <properties>
            ...
        </properties>
    </message>
</MSG_INFO>
BodyLength=31108
<?xml version="1.0" encoding="UTF-8"?>

<ns0:Envelope xmlns:ns0="http://www.wnco.com/opsplatform/flight/flightevent">
    <ns0:Header>
        <ns1:EventHeader xmlns:ns1="http://www.wnco.com/opsplatform/event/header">
            ...
        </ns1:EventHeader>
    </ns0:Header>
    <ns0:Body>
        <ns1:Flight xmlns:ns1="http://www.wnco.com/opsplatform/flight/flight">
           <ns2:ScheduledFlightLeg xmlns:ns2="http://www.wnco.com/opsplatform/flight/flight/scheduledflightleg">
                ...
                <ns3:OperationalFlightLeg xmlns:ns3="http://www.wnco.com/opsplatform/flight/flight/operationalflightleg">
                    ...
                </ns3:OperationalFlightLeg>
            </ns2:ScheduledFlightLeg>
            <ns2:ScheduledFlightLeg xmlns:ns2="http://www.wnco.com/opsplatform/flight/flight/scheduledflightleg">
                ...
                    ...
                </ns3:OperationalFlightLeg>
            </ns2:ScheduledFlightLeg>
            <ns2:ScheduledFlightLeg xmlns:ns2="http://www.wnco.com/opsplatform/flight/flight/scheduledflightleg">
               ...
                    ...
                </ns3:OperationalFlightLeg>
            </ns2:ScheduledFlightLeg>
            <ns2:ScheduledFlightLeg xmlns:ns2="http://www.wnco.com/opsplatform/flight/flight/scheduledflightleg">
                ...
                    ...
                </ns3:OperationalFlightLeg>
            </ns2:ScheduledFlightLeg>
        </ns1:Flight>
    </ns0:Body>
</ns0:Envelope>

#---------- #3 : ID:QADC1_HGR1-EMS13112.15DB4FBEA3665328B:4985 ----------#
        <MSG_INFO>
            <message type="TextMessage" messageSelector="" receiveTime="2012-09-12T14:37:26.717" jmsServerTimestamp="2012-09-12T14:37:26.775">
                <header JMSMessageID="ID:QADC1_HGR1-EMS13112.15DB4FBEA3665328B:4985" JMSDestination="OPS.FPES.OUTBOUND.FLIGHT.TRACK_A.DISTRIBUTION" JMSDestinationType="Topic" JMSDeliveryMode="2" JMSPriority="4" JMSTimestamp="1347478646775"/>
                <properties>
                    ...
                </properties>
            </message>
        </MSG_INFO>
        BodyLength=31108
        <?xml version="1.0" encoding="UTF-8"?>

        <ns0:Envelope xmlns:ns0="http://www.wnco.com/opsplatform/flight/flightevent">
            <ns0:Header>
                <ns1:EventHeader xmlns:ns1="http://www.wnco.com/opsplatform/event/header">
                    ...
                </ns1:EventHeader>
            </ns0:Header>
            <ns0:Body>
                <ns1:Flight xmlns:ns1="http://www.wnco.com/opsplatform/flight/flight">
                   <ns2:ScheduledFlightLeg xmlns:ns2="http://www.wnco.com/opsplatform/flight/flight/scheduledflightleg">
                        ...
                        <ns3:OperationalFlightLeg xmlns:ns3="http://www.wnco.com/opsplatform/flight/flight/operationalflightleg">
                            ...
                        </ns3:OperationalFlightLeg>
                    </ns2:ScheduledFlightLeg>
                    <ns2:ScheduledFlightLeg xmlns:ns2="http://www.wnco.com/opsplatform/flight/flight/scheduledflightleg">
                        ...
                            ...
                        </ns3:OperationalFlightLeg>
                    </ns2:ScheduledFlightLeg>
                    <ns2:ScheduledFlightLeg xmlns:ns2="http://www.wnco.com/opsplatform/flight/flight/scheduledflightleg">
                       ...
                            ...
                        </ns3:OperationalFlightLeg>
                    </ns2:ScheduledFlightLeg>
                    <ns2:ScheduledFlightLeg xmlns:ns2="http://www.wnco.com/opsplatform/flight/flight/scheduledflightleg">
                        ...
                            ...
                        </ns3:OperationalFlightLeg>
                    </ns2:ScheduledFlightLeg>
                </ns1:Flight>
            </ns0:Body>
        </ns0:Envelope>
4

3 回答 3

1

使用 JAVA Scanner 根据每个 XML 的唯一属性提取 XML。

 public static void main(String[] args) {
      String temp = null;
      String searchedData = null;
      File file = new File(fileLocation);
      try{
            Scanner scan = new Scanner (file);
            scan.useDelimiter("xml version");
            while (scan.hasNext()){
                  temp = scan.next();
                  if(temp.contains("<ns1:EventCorrelationID>153721264</ns1:EventCorrelationID>")){
                        searchedData = temp.substring(0, temp.lastIndexOf("</ns0:Envelope>")+15);
                        System.out.println("xml version"+searchedData);
                  }
            }
      }catch(Exception e){
            e.printStackTrace();
      }
}
于 2012-09-20T15:54:41.270 回答
0

好吧,您当然不应该通过将 500Mb 的数据加载到 Java 字符串中然后对字符串应用正则表达式来执行此操作,这似乎就是您正在做的事情。您需要对文件进行缓冲读取并检查每个缓冲区的内容,注意检查跨越从一个缓冲区到下一个缓冲区边界的分隔符。

于 2012-09-20T15:31:41.137 回答
0

您真的应该只使用 SAX 解析器。SAX 解析器不会一次读取整个文档,而是按顺序读取元素,并且仅在读取时才将其加载到内存中。这与您尝试做的事情和 DOM 解析器相反。

于 2012-09-20T14:42:55.707 回答