如何将ZipInputStream转换为InputStream?

4

我有一段代码,其中ZipInputStream被转换为byte[],但我不知道如何将其转换为InputStream。

private void convertStream(String encoding, ZipInputStream in) throws IOException,
        UnsupportedEncodingException
{
    final int BUFFER = 1;
    @SuppressWarnings("unused")
    int count = 0;
    byte data[] = new byte[BUFFER];
    while ((count = in.read(data, 0, BUFFER)) != -1) 
    {
       // How can I convert data to InputStream  here ?                    
    }
}

你到底想做什么?是在流中解压单个条目吗? - Jon Skeet
是的,如果可能的话,我希望从流中获得单个文件作为InputStream。 - newbie
6个回答


3

以下是我解决这个问题的方法。现在我可以将ZipInputStream中的单个文件作为InputStream存储到内存中。

private InputStream convertZipInputStreamToInputStream(ZipInputStream in, ZipEntry entry, String encoding) throws IOException
{
    final int BUFFER = 2048;
    int count = 0;
    byte data[] = new byte[BUFFER];
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    while ((count = in.read(data, 0, BUFFER)) != -1) {
        out.write(data);
    }       
    InputStream is = new ByteArrayInputStream(out.toByteArray());
    return is;
}

请问您能否指明ZipEntry entry,String encoding在哪里使用以及为什么使用它们? - Adi
1
你应该避免这样做,因为它会在大文件上引起OutOfMemoryError。相反,你可以使用ZipInputStream。请参考https://dev59.com/knnZa4cB1Zd3GeqPnTcP#20021055?noredirect=1#20021055。 - Tim Autin
第二个和第三个参数是用来干什么的?它们根本没有被使用。 - user207421
1
while ((count = in.read(buffer)) > 0) {out.write(BUFFER, 0, count);} - LovaBill
2
你不需要这些,正如ExtremeCoder所指出的那样。ZipInputStream是一个InputStream,或者如果你喜欢的话,“private InputStream convertZipInputStreamToInputStream(ZipInputStream in) { return in; }”。 - Alejadro Xalabarder
1
这个特定的答案将在 out 流中使用 out.write(data) 添加额外的数据。正确的方式应该是 out.write(data, 0, count)。当问题就在这里时,我浪费了很多时间在代码中找问题。请参考此答案:https://stackoverflow.com/a/19473853/7630458。 - 11t

0
请查看下面的函数示例,它将从 ZIP 存档中提取所有文件。该函数无法处理子文件夹中的文件:
private static void testZip() {
    ZipInputStream zipStream = null;
    byte buff[] = new byte[16384];
    int readBytes;
    try {
        FileInputStream fis = new FileInputStream("./test.zip");
        zipStream = new ZipInputStream(fis);
        ZipEntry ze;
        while((ze = zipStream.getNextEntry()) != null) {
            if(ze.isDirectory()) {
                System.out.println("Folder : "+ze.getName());
                continue;//no need to extract
            }
            System.out.println("Extracting file "+ze.getName());
            //at this moment zipStream pointing to the beginning of current ZipEntry, e.g. archived file
            //saving file
            FileOutputStream outFile = new FileOutputStream(ze.getName());
            while((readBytes = zipStream.read(buff)) != -1) {
                outFile.write(buff, 0, readBytes);
            }
            outFile.close();                
        }

    } catch (Exception e) {
        System.err.println("Error processing zip file : "+e.getMessage());
    } finally {
        if(zipStream != null)
            try {
                zipStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
}

Not what was asked for. - user207421

0

以下代码对于 FileOutputStream 对象在我的环境下有效:

try (ZipInputStream zin = new ZipInputStream(response.getInputStream())) {
        for (ZipEntry zipEntry = zin.getNextEntry(); zipEntry != null; zipEntry = zin.getNextEntry()) {
            File f = new File(dir, zipEntry.getName());
            try (FileOutputStream fout = new FileOutputStream(f)) {
                 int len;
                 byte[] buffer = new byte[1024];
                 while ((len = zin.read(buffer)) > 0) {
                     fout.write(buffer, 0, len);
                 }
                zin.closeEntry();
            }
        }
    }

-1

ZipInputStream 允许直接读取 ZIP 内容:使用 getNextEntry() 进行迭代,直到找到要读取的条目,然后从 ZipInputStream 中读取即可。

如果您不仅想读取 ZIP 内容,而且需要在传递到下一步之前对流应用其他转换,则可以使用 PipedInputStreamPipedOutputStream。其思路类似于以下代码(根据记忆编写,可能无法编译):

import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public abstract class FilterThread extends Thread {
    private InputStream unfiltered;
    public void setUnfilteredStream(InputStream unfiltered) {
        this.unfiltered = unfiltered;
    }
    private OutputStream threadOutput;
    public void setThreadOutputStream(OutputStream threadOutput) {
        this.threadOutput = threadOutput;
    }    

    // read from unfiltered stream, filter and write to thread output stream
    public abstract void run();
}

...

public InputStream getFilteredStream(InputStream unfiltered, FilterThread filter) {
    PipedInputStream filteredInputStream = new PipedInputStream();
    PipedOutputStream threadOutputStream = new PipedOutputStream(filteredInputStream);

    filter.setUnfilteredStream(unfiltered);
    filter.setThreadOuptut(threadOutputStream);
    filter.start();

    return filteredInputStream;
}

...

public void clientCode() {
    ...
    ZipInputStream zis = ...;// get ZIP stream
    FilterThread filter = ...; // assign your implementation of FilterThread that transforms your ZipInputStream

    InputStream filteredZipInputStream = getFilteredStream(zis, filter);
    ...
}

-2

邮政编码很简单,但是我在将ZipInputStream作为InputStream返回时遇到了问题。由于某些原因,压缩包中包含的某些文件丢失了一些字符。下面是我的解决方案,目前它一直在工作。

private Map<String, InputStream> getFilesFromZip(final DataHandler dhZ,
        String operation) throws ServiceFault
{
    Map<String, InputStream> fileEntries = new HashMap<String, InputStream>();
    try
    {

        DataSource dsZ = dhZ.getDataSource();

        ZipInputStream zipIsZ = new ZipInputStream(dhZ.getDataSource()
                .getInputStream());

        try
        {
            ZipEntry entry;
            while ((entry = zipIsZ.getNextEntry()) != null)
            {
                if (!entry.isDirectory())
                {
                    Path p = Paths.get(entry.toString());
                    fileEntries.put(p.getFileName().toString(),
                            convertZipInputStreamToInputStream(zipIsZ));
                }

            }
        }
        finally
        {
            zipIsZ.close();
        }

    }
    catch (final Exception e)
    {
        faultLocal(LOGGER, e, operation);
    }

    return fileEntries;
}
private InputStream convertZipInputStreamToInputStream(
        final ZipInputStream in) throws IOException
{
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    IOUtils.copy(in, out);
    InputStream is = new ByteArrayInputStream(out.toByteArray());
    return is;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接