Java NIO通道的StAX解析

8
我正在尝试通过Java NIO通道接收一系列XML事件流。我对NIO和StAX解析都不熟悉,所以很可能会忽略一些东西 :)
我的搜索结果显示有几个SAX和StAX实现,但它们似乎都在InputStreams和InputSources上操作,而不是NIO通道。我做过的两次最接近的尝试是从通道中获取InputStream并创建PipedInputStream:
// method 1
PipedOutputStream out = new PipedOutputStream();
InputStream in = new PipedInputStream(out);
PrintWriter writer = new PrintWriter(out);

//method 2
InputStream in = channel.socket().getInputStream()
//method 3
IputStream in = Channels.newInputStream(channel);

接下来是:

XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance()
        .createXMLStreamReader(in);
//...

当使用方法1时,上述代码会在createXMLStreamReader行阻塞。当使用方法2/3时,它们立即抛出IllegalBlockingModeException异常(我明白为什么)。也许需要一种新的方法?
我的目标是拥有一个非阻塞服务器:选择= >接受来自客户端的字符数据 = >使用特定编码解析该数据到XML事件= >将该事件对象转发到另一个线程进行处理= >并返回到选择状态。
所以我是否忽略了某些东西,或者是否有更好的方法可用?如果有,那是什么?
谢谢!

就像Fern所提到的,Aalto xml处理器具有异步模式,专门为这种用例而设计。对于异步模式并没有太多的兴趣(还没有那么多基于NIO的系统...),所有现有的用户似乎都使用BIO,但实际上它非常适合。 - StaxMan
最后,在0.9.7版本中,有一小段文档展示了如何进行非阻塞解析,请参考:http://www.cowtowncoder.com/blog/archives/2011/03/entry_451.html - StaxMan
3个回答

4

您确定需要使用NIO吗?它可能没有原本期望的相对优势:

Paul Tyma:请打破这个神话。NIO不比IO更快

Paul Tyma:编写Java多线程服务器 - 新旧何去何从

一个显示createXMLStreamReader()内部阻塞位置的堆栈可能有所帮助,但它可能是按设计行为的。如果它被设计为针对InputStreams工作,这些流总是(1)提供预期数量的数据;(2)结束;或者(3)阻塞,则它不会自动以(通常更复杂和有状态的)方式运行,可以在读取任意量的不完整输入后返回,而不需要进行大量的深度重构。


NIO并不能保证比默认I/O更快,但它确实有可能做到。 - Renascienza

2
我也开始寻找使用XMPP服务器的方法。我一直在寻找,并且似乎只有一种实现承诺提供NIO支持:Aalto http://wiki.fasterxml.com/AaltoHome。但是它似乎只发布到0.9.5版本,时间是2009年3月。因此,我不确定它是否得到了很好的维护,但这可能是一个不错的起点。除非你能说服更大的项目(也许是Woodstox),重新设计一些内部类以支持NIO。

快速评论:尽管从Aalto页面上可能不明显,但其开发人员基础与Woodstox有重叠。部分原因是Aalto的内部非常不同,而且在NIO上轻松实现BIO-based系统并不容易。另一方面,Aalto非常适合NIO - 它具有异步模式,虽然有点不完整(API未完全定义),但非常接近生产就绪状态。因此,如果有人感兴趣,请随时加入Aalto讨论论坛 - 开发人员(包括我自己)很乐意看到更多的参与。 - StaxMan

0
你需要使用java.nio.channels.Channels实用类。
ReadableByteChannel ch = //...
InputStream in = Channels.newInputStream(ch);

您可能需要配置套接字通道为阻塞模式。

SelectableChannel ch = //...
ch.configureBlocking(true);

这意味着您将无法执行非阻塞I/O操作。


是的,我发帖后注意到了这一点,我已经添加了configureBlocking调用,应该可以解决第三种方法的问题。 - Michael Barker
阻塞的问题在于我试图避免每个连接都有一个线程,而是使用单个线程读取,然后根据需要分叉出其他处理。 - Harlan Iverson
1
你和我一样:https://dev59.com/b3NA5IYBdhLWcg3wSrua - Michael Barker
嗯,现在我们正试图为完全相同的应用程序解决完全相同的问题。有趣。 - Harlan Iverson

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