在工作中,我使用 DefaultHandler
类解析大型 XML 文件。这样做时,我注意到这个接口(interface)为元素名称、属性名称和值等分配了许多 String
。
由此,我考虑创建一个只执行绝对最少对象分配的 XML 解析器。目前我需要:
- 一个 StringBuilder 用于构建元素名称、属性名称等。
- 一个 CharsetDecoder,用于将字节转换为字符。
我的测试程序,用于解析http://magnatune.com/info/song_info.xml ,看起来像这样:
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class XmlParserDemo {
public static void main(String[] args) throws IOException {
List<Map<String, String>> allSongs = new ArrayList<Map<String, String>>();
InputStream fis = new FileInputStream("d:/song_info.xml");
try {
XmlParser parser = new XmlParser(new BufferedInputStream(fis));
if (parser.element("AllSongs")) {
while (parser.element("Track")) {
Map<String, String> track = new LinkedHashMap<String, String>();
while (parser.element()) {
String name = parser.getElementName();
String value = parser.text();
track.put(name, value);
parser.endElement();
}
allSongs.add(track);
parser.endElement();
}
parser.endElement();
}
} finally {
fis.close();
}
}
}
此代码看起来比我使用 XMLEventReader
进行的实验要好。现在唯一缺少的部分是上面代码中提到的 XmlParser
类。您知道以前是否有人编写过该代码吗?这实际上只是我的一个宠物项目,但我很好奇“对象创建很昂贵”这一旧说法现在还有多少值(value)。
是的,我知道LinkedHashMap
正在使用大量内存。我实际上只是想提高内存效率的解析部分。其他一切只是为了做一个简单的例子。
最佳答案
“对象创建成本高昂”在 Java 中很长一段时间以来都不是事实。分配通常非常便宜(移动指针),并且垃圾收集已经取得了长足的进步。
我肯定使用 XML API,它可以让您轻松地做您想做的事情,而不必过多担心过多的内存分配,除非您认为您将突破性能极限。
我确信有 XML API 被设计为具有特别小的内存占用 - 但您的 XML 文件到底有多大?如果它们足够小,可以轻松装入内存,我就不会担心……如果它们太大,您确实需要考虑使用流式 API。我怀疑,就适用性而言,特别高效的解析器可以将其放入内存但“普通”解析器不能放入的大小范围相对较小。
关于Java XML 解析器无需过多内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3250921/