代码之家  ›  专栏  ›  技术社区  ›  Fedearne

在Java中检测流是否被压缩的最好方法

  •  19
  • Fedearne  · 技术社区  · 15 年前

    找到我最好的方法是什么 java.io.InputStream 包含压缩数据?

    5 回复  |  直到 8 年前
        1
  •  22
  •   McDowell rahul gupta    15 年前

    这个 magic bytes 因为zip格式是 50 4B . 您可以测试流(使用 mark reset -你可能需要 buffer )但我不希望这是一个100%可靠的方法。无法将其与以字母开头的US-ASCII编码文本文件区分开来。 PK .

    这个 最好的 方法是在打开流之前提供内容格式的元数据,然后对其进行适当的处理。

        2
  •  36
  •   Community Tales Farias    7 年前

    介绍

    既然所有的答案都是5岁,我觉得有责任写下来,今天发生了什么。我真的怀疑一个人是否应该读到流的神奇字节!这是一个低级代码,一般来说应该避免。

    简单答案

    米库写道:

    如果流可以通过zipinputstream读取,则应该对其进行压缩。

    是的,但是如果 ZipInputStream “可以读”是指第一次呼叫 .getNextEntry() 返回非空值。抓捕et-cetera也不例外。因此,您可以执行以下操作,而不是神奇的字节解析:

    boolean isZipped = new ZipInputStream(yourInputStream).getNextEntry() != null;
    

    就这样!

    一般解压思想

    一般来说,在压缩文件时使用文件似乎比使用流更方便。有几个有用的库,另外ZipFile比ZipInputStream有更多的功能。此处讨论压缩文件的处理: What is a good Java library to zip/unzip files? 所以,如果你能处理文件,你最好这样做!

    代码样本

    我需要在应用程序中只使用流。这就是我写的解压方法:

    import org.apache.commons.io.IOUtils;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipInputStream;
    
    public boolean unzip(InputStream inputStream, File outputFolder) throws IOException {
    
        ZipInputStream zis = new ZipInputStream(inputStream);
    
        ZipEntry entry;
        boolean isEmpty = true;
        while ((entry = zis.getNextEntry()) != null) {
            isEmpty = false;
            File newFile = new File(outputFolder, entry.getName());
            if (newFile.getParentFile().mkdirs() && !entry.isDirectory()) {
                FileOutputStream fos = new FileOutputStream(newFile);
                IOUtils.copy(zis, fos);
                IOUtils.closeQuietly(fos);
            }
        }
    
        IOUtils.closeQuietly(zis);
        return !isEmpty;
    }
    
        3
  •  6
  •   David Webb    15 年前

    您可以检查流的前四个字节是否是 本地文件头签名 开始 本地文件头 在压缩文件中处理每个文件, as shown in the spec here 成为 50 4B 03 04 .

    一个小测试代码显示了这一点:

    byte[] buffer = new byte[4];
    
    try {
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("so.zip"));
        ZipEntry ze = new ZipEntry("HelloWorld.txt");
        zos.putNextEntry(ze);
        zos.write("Hello world".getBytes());
        zos.close();
    
        FileInputStream is = new FileInputStream("so.zip");
        is.read(buffer);
        is.close();
    }
    catch(IOException e) {
        e.printStackTrace();
    }
    
    for (byte b : buffer) { 
        System.out.printf("%H ",b);
    }
    

    给了我这个输出:

    50 4B 3 4 
    
        4
  •  5
  •   miku    15 年前

    不太优雅,但可靠:

    如果流可以通过 ZipInputStream ,应该有拉链。

        5
  •  0
  •   kk nair    9 年前

    检查幻数可能不是正确的选择。

    docx文件也有类似的神奇数字50 4b 3 4