【发布时间】:2017-09-08 01:24:54
【问题描述】:
有没有办法使用 StAX 和 JAX-B 创建索引,然后快速访问 XML 文件?
我有一个很大的 XML 文件,我需要在其中查找信息。这用于桌面应用程序,因此它应该在 RAM 很少的系统上工作。
所以我的想法是这样的:创建一个索引,然后快速访问大文件中的数据。
我不能只拆分文件,因为它是一个官方的联邦数据库,我想原封不动地使用。
使用 XMLStreamReader 我可以快速找到一些元素,然后使用 JAXB 来解组元素。
final XMLStreamReader r = xf.createXMLStreamReader(filename, new FileInputStream(filename));
final JAXBContext ucontext = JAXBContext.newInstance(Foo.class);
final Unmarshaller unmarshaller = ucontext.createUnmarshaller();
r.nextTag();
while (r.hasNext()) {
final int eventType = r.next();
if (eventType == XMLStreamConstants.START_ELEMENT && r.getLocalName().equals("foo")
&& Long.parseLong(r.getAttributeValue(null, "bla")) == bla
) {
// JAX-B works just fine:
final JAXBElement<Foo> foo = unmarshaller.unmarshal(r,Foo.class);
System.out.println(foo.getValue().getName());
// But how do I get the offset?
// cache.put(r.getAttributeValue(null, "id"), r.getCursor()); // ???
break;
}
}
但我无法获得偏移量。我想用它来准备一个索引:(id of element) -> (offset in file)
然后我应该能够使用偏移量从那里解组:打开文件流,跳过那么多字节,解组。 我找不到这样做的图书馆。如果不知道文件光标的位置,我不能自己做。 javadoc 明确指出有一个游标,但我找不到访问它的方法。
编辑:
我只是想提供一种适用于旧硬件的解决方案,以便人们可以实际使用它。不是每个人都能买得起一台功能强大的新电脑。使用 StAX 我可以在大约 2 秒内获取数据,这有点长。但它不需要内存。它需要 300 MB 的 RAM 才能使用 JAX-B。对于这样一个简单的任务,使用一些嵌入式数据库系统只会带来很多开销。无论如何,我都会使用 JAX-B。因为 wsimport 生成的类已经很完美了,所以其他任何东西对我来说都是无用的。当我只需要一些对象时,我只是不想加载 300 MB 的对象。
我找不到只需要 XSD 来创建内存数据库的数据库,它不使用那么多 RAM。这一切都是为服务器设计的,或者需要定义模式和映射 XML。所以我认为它只是不存在。
【问题讨论】:
-
为什么不是内存数据库? XML 是一种存储信息的可怕方式。
-
你试过
r.getLocation().getCharacterOffset()吗? -
内存中使用的内存是未压缩的 xml 文件的 3 倍。这对于桌面应用程序来说有点太多了。所以我想使用索引访问。
-
真的吗?您尝试了哪个内存数据库?氢2? SQLite? XML 作为一种传输格式是可以接受的,但作为一种存储格式(带有操作),它真的是纯粹的垃圾。
-
@jschnasse:是的,但 javadoc 声明:“位置提供的所有信息都是可选的。例如,应用程序可能只报告行号。”我得到了光标的位置,但是是当前元素的位置。它已经读到下一个元素。这不是导致
START_ELEMENT的元素的开头。
标签: java xml jaxb stax random-access