我正在使用 VTD-XML 解析大量 XML 文件。我不确定我是否正确使用了该工具 - 我想是这样,但是解析文件花费了我太长时间。
xml 文件(DATEXII 格式)是 HD 上的压缩文件。解压后它们大约有 31MB 大,包含超过 850.000 行文本。我只需要提取几个字段并将它们存储在数据库中。
import org.apache.commons.lang3.math.NumberUtils;
...
private static void test(File zipFile) throws XPathEvalException, NavException, XPathParseException {
// init timer
long step1=System.currentTimeMillis();
// open file to output extracted fragments
VTDGen vg = new VTDGen();
vg.parseZIPFile(zipFile.getAbsolutePath(), zipFile.getName().replace(".zip",".xml"),true);
VTDNav vn = vg.getNav();
AutoPilot apSites = new AutoPilot();
apSites.declareXPathNameSpace("ns1", "http://schemas.xmlsoap.org/soap/envelope/");
apSites.selectXPath("/ns1:Envelope/ns1:Body/d2LogicalModel/payloadPublication/siteMeasurements");
apSites.bind(vn);
long step2=System.currentTimeMillis();
System.out.println("Prep took "+(step2-step1)+"ms; ");
// init variables
String siteID, timeStr;
boolean reliable;
int index, flow, ctr=0;
short speed;
while(apSites.evalXPath()!=-1) {
vn.toElement(VTDNav.FIRST_CHILD, "measurementSiteReference");
siteID = vn.toString(vn.getText());
// loop all measured values of this measurement site
while(vn.toElement(VTDNav.NEXT_SIBLING, "measuredValue")) {
ctr++;
// extract index attribute
index = NumberUtils.toInt(vn.toString(vn.getAttrVal("index")));
// go one level deeper into basicDataValue
vn.toElement(VTDNav.FIRST_CHILD, "basicDataValue");
// we need either FIRST_CHILD or NEXT_SIBLING depending on whether we find something
int next = VTDNav.FIRST_CHILD;
if(vn.toElement(next, "time")) {
timeStr = vn.toString(vn.getText());
next = VTDNav.NEXT_SIBLING;
}
if(vn.toElement(next, "averageVehicleSpeed")) {
speed = NumberUtils.toShort(vn.toString(vn.getText()));
next = VTDNav.NEXT_SIBLING;
}
if(vn.toElement(next, "vehicleFlow")) {
flow = NumberUtils.toInt(vn.toString(vn.getText()));
next = VTDNav.NEXT_SIBLING;
}
if(vn.toElement(next, "fault")) {
reliable = vn.toString(vn.getText()).equals("0");
}
// insert into database here...
if(next==VTDNav.NEXT_SIBLING) {
vn.toElement(VTDNav.PARENT);
}
vn.toElement(VTDNav.PARENT);
}
}
System.out.println("Loop took "+(System.currentTimeMillis()-step2)+"ms; ");
System.out.println("Total number of measured values: "+ctr);
}
我的 XML 文件的上述函数的输出是:
Prep took 25756ms;
Loop took 26889ms;
Total number of measured values: 112611
现在实际上没有数据插入到数据库中。现在的问题是我每分钟都会收到一个这些文件。现在总解析时间将近 1 分钟,因为下载文件大约需要 10 秒,而且我需要将内容存储在数据库中,所以我现在正在实时运行。
有什么办法可以加快这个速度吗?我尝试过的没有帮助的事情:
- 对所有字段使用自动驾驶仪,这实际上使第二步慢了 30000ms
- 自己解压缩文件并将字节数组解析为VTD,这没有任何区别
- 使用 BufferedReader readLine() 自己循环文件,但这也不够快
有没有人看到加快速度的可能性,还是我需要开始考虑更重的机器/多线程?当然,每分钟 850.000 行(每天 12 亿行)很多,但我仍然觉得解析 31MB 的数据不应该花一分钟...