在Java中读取大型XML文件的最快方法

3

我正在进行一个Java项目,优化现有的代码。目前我正在使用BufferedReader/FileInputStream在Java中读取XML文件的内容作为字符串。

但我的问题是,是否有更快的方法来读取XML内容。SAX/DOM比BufferedReader/FileInputStream更快吗?

需要关于上述问题的帮助。

提前感谢。


2
不确定您的意思......使用BufferedReader/FileInputStream读取文件将获得字节,但不是作为XML文档...... SAX/DOM解析器都会读取文件,然后将XML解析成更有用的结构。通常情况下,SAX解析器比DOM解析器更快。 - Buddy
经过对应用程序进行压力测试和使用性能分析工具,您认为这部分代码是瓶颈吗?如果是,那么在读取 XML 文件时,不要将其作为字符串再解析,而是建议使用 SAX 解析器,因为它比 DOM 解析快。 - Luiggi Mendoza
我指的是使用BufferedReader b = new BufferedReader(new InputStreamReader(new FileInputStream(filename), Charset.forName("UTF-8")))。其中filename是XML文件,b包含整个XML文件数据。现在我逐行解析数据并提取特定字段进行打印。 - bigdata123
我正在寻找解析XML文档的最快方法,应该比使用BufferedReader更快。请在这方面提供帮助。 - bigdata123
@Mohana 除非您的解析代码很慢,否则没有什么比读取原始流更快的了。但是您并没有发布那段代码,我们怎么能说呢?现在,自己读取和解析XML是有问题的。您的代码是否正确处理所有怪癖?最好使用内置的解析器,例如SAX或StAX,而不是DOM,因为在大型XML文件上会耗尽内存。 - Andreas
除非你在对数据进行一些操作,否则解析XML文档是没有意义的,在许多应用中,“做某事”就是瓶颈。但是,在你可以对数据进行操作之前,你需要从磁盘上读取文件并解析它。解析比从磁盘上读取文件更为复杂,那么为什么你还这么关注读取任务呢? - Michael Kay
2个回答

8
我认为你在其他问题中展示的代码比类似DOM解析器更快,后者肯定需要更多的内存并且可能需要一些计算才能完整重构文档。不过你可能需要对代码进行分析。
我还认为,如果你使用javax XMLStreamReader,你的代码可以在流处理方面变得更加美观,我发现这对许多任务非常有帮助。根据Oracle的说法,该类是“...设计为读取XML数据的最低级别和最有效的方式”(参考链接)
下面是我从代码中摘录的部分,用于解析作为公共数据转储分发的StackOverflow用户XML文件:
// the input file location
private static final String fileLocation = "/media/My Book/Stack/users.xml";

// the target elements
private static final String USERS_ELEMENT = "users";
private static final String ROW_ELEMENT = "row";

// get the XML file handler
//
FileInputStream fileInputStream = new FileInputStream(fileLocation);
XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(
    fileInputStream);

// reading the data
//
while (xmlStreamReader.hasNext()) {

  int eventCode = xmlStreamReader.next();

  // this triggers _users records_ logic
  //
  if ((XMLStreamConstants.START_ELEMENT == eventCode)
      && xmlStreamReader.getLocalName().equalsIgnoreCase(USERS_ELEMENT)) {

    // read and parse the user data rows
    //
    while (xmlStreamReader.hasNext()) {

      eventCode = xmlStreamReader.next();

      // this breaks _users record_ reading logic
      //
      if ((XMLStreamConstants.END_ELEMENT == eventCode)
          && xmlStreamReader.getLocalName().equalsIgnoreCase(USERS_ELEMENT)) {
        break;
      }
      else {

        if ((XMLStreamConstants.START_ELEMENT == eventCode)
            && xmlStreamReader.getLocalName().equalsIgnoreCase(ROW_ELEMENT)) {

          // extract the user data
          //
          User user = new User();
          int attributesCount = xmlStreamReader.getAttributeCount();
          for (int i = 0; i < attributesCount; i++) {
            user.setAttribute(xmlStreamReader.getAttributeLocalName(i),
                xmlStreamReader.getAttributeValue(i));
          }
          // all other user record-related logic
          //

        }
      }
    }
  }
}

用户文件格式非常简单,类似于您的Bank.xml文件:

<users>
  <row Id="1567200" Reputation="1" CreationDate="2012-07-31T23:57:57.770" DisplayName="XXX" EmailHash="XXX" LastAccessDate="2012-08-01T00:55:12.953" Views="0" UpVotes="0" DownVotes="0" />
  ...
</users>

0

有不同的解析器选项可用。

考虑使用流式解析器,因为DOM可能会变得非常大。即推送或拉取解析器。

并不是XML解析器一定很慢。考虑你的网络浏览器。它一直在进行XML解析,并努力对语法错误进行鲁棒性处理。通常,内存是更大的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接