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

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

我希望在标签完成后我会得到一个事件.

以下测试显示了我的意思:

@Test
public void sax_parser_read_much_things_before_returning_events() throws Exception{
    String xml = "stem.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 qName) throws SAXException {
            System.out.print("\nHandler end: " + qName);
        }
    });
}

我将输入流包装起来以查看读取的内容以及事件发生的时间.

我的期望是这样的:

可悲的是结果如下:

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

编辑:

>首先,他正在尝试检测doc版本,这会导致扫描所有内容.随着doc版本,他介于两者之间(但不是我期望的)
>他“想要”读取例如1000字节和块这么长时间是不正确的,因为它可能在这个时间点不包含这么多的流.
>我在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解析器将以块的形式请求数据,因为从流中请求单个字节是导致性能灾难的方法.

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

@Test
public void sax_parser_read_much_things_before_returning_events() throws Exception{
    final String xml = "stem.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,String qName) throws SAXException {
            System.out.print("\nHandler end: " + qName);
        }
    });
}

这将打印

显示,XML解析器如何适应InputStream中数据的可用性.

相关文章

应用场景 C端用户提交工单、工单创建完成之后、会发布一条工...
线程类,设置有一个公共资源 package cn.org.chris.concurre...
Java中的数字(带有0前缀和字符串)
在Java 9中使用JLink的目的是什么?
Java Stream API Filter(过滤器)
在Java中找到正数和负数数组元素的数量