gpt4 book ai didi

java - 为什么 SAXParser 在抛出事件之前读取这么多?

转载 作者:数据小太阳 更新时间:2023-10-29 01:57:56 26 4
gpt4 key购买 nike

场景:我通过极慢的网络接收到一个巨大的 xml 文件,所以我希望尽早开始过多的处理。因此,我决定使用 SAXParser。

我预计在标记完成后我会收到一个事件。

下面的测试说明了我的意思:

@Test
public void sax_parser_read_much_things_before_returning_events() throws Exception{
String xml = "<a>"
+ " <b>..</b>"
+ " <c>..</c>"
// much more ...
+ "</a>";

// wrapper to show what is read
InputStream is = new InputStream() {
InputStream is = new ByteArrayInputStream(xml.getBytes());

@Override
public int read() throws IOException {
int val = is.read();
System.out.print((char) val);
return val;
}
};

SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(is, new DefaultHandler(){
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.print("\nHandler start: " + qName);
}

@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.print("\nHandler end: " + qName);
}
});
}

我包装了输入流以查看读取的内容以及事件发生的时间。

我期望的是这样的:

<a>                    <- output from read()
Handler start: a
<b> <- output from read()
Handler start: b
</b> <- output from read()
Handler end: b
...

遗憾的是结果如下:

<a>  <b>..</b>  <c>..</c></a>        <- output from read()
Handler start: a
Handler start: b
Handler end: b
Handler start: c
Handler end: c
Handler end: a

我的错误在哪里,我怎样才能得到预期的结果?

编辑:

  • 第一件事是他试图检测文档版本,这会导致扫描所有内容。对于 doc 版本,他介于两者之间(但不是我期望的)
  • 他“想要”读取 1000 个字节和 block 这么长时间是不行的,因为此时流可能不包含那么多内容。
  • 我在 XMLEntityManager 中找到了缓冲区大小:
    • public static final int DEFAULT_BUFFER_SIZE = 8192;
    • public static final int DEFAULT_XMLDECL_BUFFER_SIZE = 64;
    • public static final int DEFAULT_INTERNAL_BUFFER_SIZE = 1024;

最佳答案

您似乎对 I/O 的工作方式做出了错误的假设。与大多数软件一样,XML 解析器将以 block 的形式请求数据,因为从流中请求单个字节会导致性能灾难。

这并不意味着缓冲区必须在读取尝试返回之前完全填满。只是,ByteArrayInputStream 无法模拟网络 InputStream 的行为。您可以通过覆盖 read(byte[], int, int) 并且不返回完整的缓冲区来轻松解决此问题,例如每个请求一个字节:

@Test
public void sax_parser_read_much_things_before_returning_events() throws Exception{
final String xml = "<a>"
+ " <b>..</b>"
+ " <c>..</c>"
// much more ...
+ "</a>";

// wrapper to show what is read
InputStream is = new InputStream() {
InputStream is = new ByteArrayInputStream(xml.getBytes());

@Override
public int read() throws IOException {
int val = is.read();
System.out.print((char) val);
return val;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return super.read(b, off, 1);
}
};

SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(is, new DefaultHandler(){
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.print("\nHandler start: " + qName);
}

@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.print("\nHandler end: " + qName);
}
});
}

这将打印

<a>  
Handler start: a<b>
Handler start: b..</b>
Handler end: b <c>
Handler start: c..</c>
Handler end: c</a>
Handler end: a?

展示了 XML 解析器如何适应来自 InputStream 的数据可用性。

关于java - 为什么 SAXParser 在抛出事件之前读取这么多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33234298/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com