首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从InputStream条目创建ZipInputStream

从InputStream条目创建ZipInputStream
EN

Stack Overflow用户
提问于 2013-11-16 16:43:14
回答 4查看 5.5K关注 0票数 9

我想编写一个方法,从一个InputStream中读取一个ZIP中的多个XML文件。

该方法将打开一个ZipInputStream,并在每个xml文件上获取相应的InputStream,并将其交给我的XML解析器。下面是该方法的框架:

代码语言:javascript
复制
private void readZip(InputStream is) throws IOException {

    ZipInputStream zis = new ZipInputStream(is);
    ZipEntry entry = zis.getNextEntry();

    while (entry != null) {

        if (entry.getName().endsWith(".xml")) {

            // READ THE STREAM
        }
        entry = zis.getNextEntry();
    }
}

有问题的部分是"//读取流“。我有一个可行的解决方案,它包括创建一个ByteArrayInputStream,并将它提供给我的解析器。但是它使用一个缓冲区,对于大型文件,我得到一个OutOfMemoryError。这是代码,如果有人还感兴趣的话:

代码语言:javascript
复制
int count;
byte buffer[] = new byte[2048];
ByteArrayOutputStream out = new ByteArrayOutputStream();
while ((count = zis.read(buffer)) != -1) { out.write(buffer, 0, count); }       
InputStream is = new ByteArrayInputStream(out.toByteArray());

理想的解决方案是向解析器提供原始ZipInputStream。它应该能工作,因为如果我只是用扫描仪打印条目内容,它就能工作:

代码语言:javascript
复制
Scanner sc = new Scanner(zis);
while (sc.hasNextLine())
{
    System.out.println(sc.nextLine());
}

但是..。我目前使用的解析器(jdom2,但我也尝试过使用javax.xml.parsers.DocumentBuilderFactory)在解析数据:/之后关闭了流。所以我无法获得下一个条目并继续。

因此,最后的问题是:

  • 有人知道不关闭流的DOM解析器吗?
  • 还有其他方法可以从InputStream中获得ZipEntry吗?

谢谢。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-11-16 16:50:19

您可以包装ZipInputStream并拦截对close()的调用。

票数 3
EN

Stack Overflow用户

发布于 2013-12-11 07:52:52

提姆解决方案的一个小改进:在close()之前必须调用allowToBeClosed()的问题是,当处理异常时,它会使关闭ZipInputStream变得非常困难,并且会破坏Java7的试用式资源语句。

我建议创建包装类,如下所示:

代码语言:javascript
复制
public class UncloseableInputStream extends InputStream {
  private final InputStream input;

  public UncloseableInputStream(InputStream input) {
    this.input = input;
  }

  @Override
  public void close() throws IOException {} // do not close the wrapped stream

  @Override
  public int read() throws IOException {
    return input.read();
  }

  // delegate all other InputStream methods as with read above
}

这样就可以安全地使用如下:

代码语言:javascript
复制
try (ZipInputStream zipIn = new ZipInputStream(...))
{
  DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
  ZipEntry entry;
  while (null != (entry = zipIn.getNextEntry()))
  {
    if ("file.xml".equals(entry.getName())
    {
      Document doc = db.parse(new UncloseableInputStream(zipIn));
    }
  }
}
票数 7
EN

Stack Overflow用户

发布于 2013-11-16 17:01:10

由于使用了半位,我最终得到了自己的ZipInputStream类,它覆盖了close方法:

代码语言:javascript
复制
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipInputStream;

public class CustomZipInputStream extends ZipInputStream {

    private boolean _canBeClosed = false;

    public CustomZipInputStream(InputStream is) {
        super(is);
    }

    @Override
    public void close() throws IOException {

        if(_canBeClosed) super.close();
    }

    public void allowToBeClosed() { _canBeClosed = true; }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20020982

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档