Java ZipInputStream中的XMLEventReader关闭流

Java ZipInputStream中的XMLEventReader关闭流,java,xml,stream,zip,Java,Xml,Stream,Zip,我想流式传输一个包含几个非常大(~1G字节)XML文件的ZIP文件。我可以将每个zip文件中的数据读入缓冲区,并从中创建XMLStream——但为了节省内存,我更愿意动态处理数据 @Test public void zipStreamTest() throws IOException, XMLStreamException { FileInputStream fis = new FileInputStream("archive.zip"); ZipInputS

我想流式传输一个包含几个非常大(~1G字节)XML文件的ZIP文件。我可以将每个zip文件中的数据读入缓冲区,并从中创建XMLStream——但为了节省内存,我更愿意动态处理数据

@Test
public void zipStreamTest() throws IOException, XMLStreamException {
    FileInputStream fis = new FileInputStream("archive.zip");
    ZipInputStream zis = new ZipInputStream(fis);
    ZipEntry ei;

    while ((ei = zis.getNextEntry()) != null){      
        XMLEventReader xr = XMLInputFactory.newInstance().createXMLEventReader(zis);
        while (reader.hasNext()) {
            XMLEvent xe = xr.nextEvent();
            // do some xml event processing..
        }
        zis.closeEntry();
    }
    zis.close();
}
问题是:在执行
zis.closeEntry()时,我得到了一个
java.io.IOException:Stream closed
。当我删除该行时,在
zis.getnextery()
上抛出相同的错误,如果以前的条目仍然自动打开,它将关闭这些条目

我的XML流读取器似乎正在破坏XML文件末尾的流,因此无法处理zip的其余部分

我是否有实现错误,或者我对流如何工作的概念不正确


注意:为了使这成为一个最小的可复制示例,您只需要一个zip文件“archive.zip”,其中包含任何有效的XML文件(zip中没有子目录!)。然后,您可以使用JUnit运行代码段。

您可以尝试使用
java.util.zip.ZipFile
为每个条目打开单独的InputStream:

@Test
public void zipStreamTest() throws Exception {
        ZipFile zipFile = new ZipFile("archive.zip");
        Iterator<? extends ZipEntry> iterator = zipFile.entries().asIterator();
        while (iterator.hasNext()) {
            ZipEntry ze = iterator.next();
            try (InputStream zis = zipFile.getInputStream(ze)) {
                XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(zis);
                while (reader.hasNext()) {
                    XMLEvent xe = reader.nextEvent();
                    // do some xml event processing
                }
                reader.close();
            }
        }
    }
@测试
public void zipStreamTest()引发异常{
ZipFile ZipFile=新ZipFile(“archive.zip”);

迭代器我建议使用
ZipFile
而不是
ZipInputStream
,如中所建议

但是,如果您正在处理数据流,例如在下载时,因此希望继续使用
ZipInputStream
,则应将其包装在
getnextery()循环中的from 1中:

while((ei=zis.getnextery())!=null){
XMLEventReader xr=XMLInputFactory.newInstance().createXMLEventReader(新CloseShieldInputStream(zis));
//在这里处理XML
zis.closeEntry();
}

1) 或者您选择的第三方库中的其他类似助手类。

不会显示为关闭底层源代码,除非您显式调用其
close()
方法,所以我猜您是在调用close()在某个地方。考虑在您的问题中提供一个。我建议使用<代码> zIPFrase<代码>而不是<代码> zIPunPoStuts,如建议的那样,但是如果您正在处理一个数据流,例如下载,因此希望继续使用<代码> zIPunPuthStudio,您应该将它包装为A-(或其他类似的帮助类)。在
getnextery()中
loop.@Andreas:非常感谢!您的解决方案非常有效。请将您的解决方案表述为一个答案,以便我能够接受。Re:ZipFile:这是一个显而易见的解决方案,但我的zip源和目标不是文件,而是网络流和/或数据库套接字。我从网络流获取zip,因此ZipFile不是一个合适的工具。一个dreas使用CloseShieldInputStream找到了一个解决方案,该方案使用所需的方法解决了问题。