【问题标题】:Problem opening/downloading zip-file after decompression (Java/ZipInputStream)解压后打开/下载 zip 文件的问题 (Java/ZipInputStream)
【发布时间】:2011-03-13 05:24:13
【问题描述】:

背景
目前,我尝试通过带有 HTTP 请求的 HTTP-servlet 获取 zip 文件。收到的 zip 文件包含三个不同的文件。这些文件包含我想要过滤掉的信息,并且从源头执行此操作不是一种选择(就是这样,尽管我知道它会好得多)。

因为我无法从源文件中过滤掉文件中的一些信息,文件是从头构建的,所以我的解决方案是解压文件,将这三个文件读取为字符串,然后过滤它们。最后“重建”全部为“zipfile”(inputStream)并返回inputStream。

问题
目前,我已经做了一个类来处理文件的解压和过滤。最后,我只想返回包含 zip 文件和其中三个文件的新 inputStream。

我已经将 HTTP 实体中的内容获取到 inputStream 中,解压缩此 inputStream 并将三个文件作为三个字符串获取。为了尝试看看这是否有效,我目前不想做的不仅仅是解压缩它们并关闭 inputStream 并返回它。但是当我返回 inputStream 时,这确实会导致异常:

 java.io.IOException: Attempted read on closed stream.

这是因为 inputStream 在我下面介绍的函数之外使用。当我关闭 zipInputStream 时,我可能还会关闭 inputStream 以进行进一步的工作。

当前代码

public InputStream convertInputStream(HttpEntity entity)
{
    InputStream inputStream = null;
    try
    {
        inputStream = entity.getContent();
    }
    catch (IOException e11)
    {

    }

    ZipInputStream zipInputStream = new ZipInputStream(inputStream);
    Vector <String>entryVector = new Vector<String>();
    ZipEntry entry;
    try
    {
        String entryValue;
        while((entry = zipInputStream.getNextEntry()) != null)
        {           
            System.out.println("Unzipping file: " + entry.getName() + "...");
            byte [] buf = new byte[(int) entry.getSize()];
            zipInputStream.read(buf);
            entryValue = new String(buf);
            entryVector.add(entryValue);
            zipInputStream.closeEntry();
        }
    }
    catch(IOException e)
    {
        System.out.println("error in getting next entry.");
    }
    finally
    {
        try 
        {
            zipInputStream.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        System.out.println("Unzipping done!");
    }
    return inputStream;
}

我希望我能够尽可能清楚地表达这一点。我仍然可以看到,当我无法在此函数之外显示整个解决方案时,这很难理解。

【问题讨论】:

  • "正在尝试下载相同的 zip 文件,链接更改,我无法访问该文件。" - 你能在这里提供更多细节吗?
  • 嗯。说链接更改可能不是真的,但是浏览器说找不到文件,所以不知何故,名称已损坏?我的理论是,在关闭 zipInputStream 的同时,我也在关闭底层流; inputStream(该函数执行后使用)。
  • 浏览器如何参与?您的示例读取一个 zip 文件,打印文件名,然后关闭该 zip 文件。浏览器从何而来?
  • 是的,这与错误无关,我的解释不好。调用 zipInputStream.close() 时,我得到了上面更新的异常。 edit 我清理了这个问题。 /编辑
  • 这个方法的目的是什么?

标签: java inputstream zipinputstream


【解决方案1】:

在您打印“解压缩文件”的地方,您实际上并没有解压缩任何内容。如果您想这样做,您需要使用 read() 函数从 ZipInputStream 读取条目的内容并将其写入文件。

编辑: 您可以尝试将输入流中的(压缩)zip 文件读入字节数组。然后在该数组上创建一个 ByteArrayInputStream ,然后将 ZipInputStream 包装在该数组上。然后您可以安全地关闭输入流,而无需关闭底层流。

另外,请确保文件的字符串内容实际上是有用的。 new String(byte[]) 使用默认编码创建一个字符串,所以这很可能没用。

【讨论】:

  • 嗯,当然,我错过了那个细节:P。但是,这不应该破坏原始的 zip 文件吗?
  • 不,不应该,因为文件没有改变。
  • 嗯。好的。我的问题是我有一个输入流,我想在其中更改 zip 文件中某些文件的内容。之后,我想再次压缩它并再次将其全部作为输入流,这看起来很不正常,因为您通常使用这种技术......我需要它作为输入流,因为使用了函数 IOUtils.copyLarge(inputStream,输出流);。所以改变内容并压缩后的返回值,应该是一个输入流...
  • 但是这个输入流和你得到的输入流没有任何关系。您需要从修改后的 zip 文件中返回一个新的输入流。
  • 是的,我也设法理解了这一点。我看到的问题是获得一个新的输入流......到目前为止,我已经设法获得一个 ByteArrayInputStream :),
【解决方案2】:

所以你不是通过网络“下载”?下载是指将文件从 zip 存档解压缩到本地硬盘?

您可以使用以下方法轻松解压缩 zip 文件:

    private static File unZipFile(File zipFileIn) throws Exception {
        ZipFile unZipFile = new ZipFile(zipFileIn);
        Enumeration<? extends ZipEntry> entries = unZipFile.entries();
        String topFile = null;
        while (entries.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
                if (entry.isDirectory()) {
                // Assume directories are stored parents first then children
                String extractFile = entry.getName();
                if (topFile == null) {
                    topFile = extractFile;
                }
                // This is not robust, just a quick solution
                (new File(entry.getName())).mkdir();
                continue;
            }
            copyInputStream(unZipFile.getInputStream(entry),new BufferedOutp    utStream(new FileOutputStream(entry.getName())));
        }
        unZipFile.close();
        File newFile = new File(zipFileIn.getParentFile().getAbsoluteFile(),topFile);
        return newFile;
    }

    private static final void copyInputStream(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[1024];
        int len;
            while((len = in.read(buffer)) >= 0)
            out.write(buffer, 0, len);
            in.close();
        out.close();
    }

该方法返回一个文件,它是解压文件的根目录。

也许最好就你想要做的事情提出更详细的问题。 ATM 每个人都在猜测您要做什么,而不是在寻找解决方案。

【讨论】:

  • 非常感谢。我稍后会更新我的问题,以尝试解释所有这些的目的。
【解决方案3】:

我认为你需要阅读每个条目上的内容,然后调用 entry.closeEntry()

【讨论】:

  • 是的。代码现已更新,如果尝试关闭 zipInputStream 则会引发异常。如果不是,则 zip 文件已损坏。
【解决方案4】:

听起来您正在尝试下载 zip 文件,同时以二进制 解压缩形式保存它。如果是这样的话,我会说先以二进制形式下载它,然后再将它解压缩到单独的文件磁盘。

如果你不想要两者,那么你可以选择你想要的,或者通过将纯流写入磁盘来获取二进制 zip 文件(无需使用 ZipInputStream);或者通过使用 ZipInputStream 并从每个条目中读取数据并将其写入磁盘(但不要使用普通输入流写入磁盘)。

【讨论】:

    猜你喜欢
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    • 2016-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 2016-05-05
    相关资源
    最近更新 更多