提问者:小点点

如何从zip存档中的内容检测文件类型?


我有一个包含几个gzip文件的zip存档。但是gzip文件的扩展名也是. zip。我使用ZipInputStream浏览zip存档。如何通过读取其内容而不是扩展名来检测内部文件的类型。我也不需要更改(或重置)ZipInputStream位置。

所以我需要;

  • 使用inputStream(在我的例子中为ZipInputStream)读取zip中的文件,因为zip中的zip是可能的。
  • 从其内容中查找文件类型。
  • 在从其内容中查找文件类型时,inputStream位置不应改变。因为我将继续读取下一个文件。

示例:

root/1.zip/2.zip/3.zip(实际上3是gzip)/4. txt

示例Java代码:

public static void main(String[] args) {
    //root/1.zip/2.zip/3.zip(actually 3 is gzip)/4.txt
    String file = "root/1.zip";
    File rootZip = new File(file);
    try (FileInputStream fis = new FileInputStream(rootZip)) {
        lookupInZip(fis)
                .stream()
                .forEach(System.out::println);
    } catch (IOException e) {
        System.out.println("Failed to get files");
    }
}

public static List<String> lookupInZip(InputStream inputStream) throws IOException {
    Tika tika = new Tika();
    List<String> paths = new ArrayList<>();
    ZipInputStream zipInputStream = new ZipInputStream(inputStream);
    ZipEntry entry = zipInputStream.getNextEntry();
    while (entry != null) {
        String entryName = entry.getName();
        if (!entry.isDirectory()) {
            //Option 1
            //String fileType = tika.detect(entryName);
            //Option 2
            String fileType = tika.detect(zipInputStream);
            if ("application/zip".equals(fileType)) {
                List<String> innerPaths = lookupInZip(zipInputStream);
                paths.addAll(innerPaths);
            } else {
                paths.add(entryName);
            }
        }
        entry = zipInputStream.getNextEntry();
    }
    return paths;
}

如果我使用选项1,'3.zip'被评估为zip文件,但它是gzip。如果我使用选项2,'2.zip'通过使用其内容被正确评估为zip。但是当递归调用lookupInZip()用于'3.zip'时,zipInputStream. getNextEntry()返回null。因为在上一步中,我们使用inputStream内容来检测类型和inputStrem位置更改。

注意:tika.检测()在实现中使用BufferedInputStream来重置inputStream位置,但它并不能解决我的问题。


共1个答案

匿名用户

前两个字节足以查看它是否可能是zip文件、gzip文件或其他文件。

如果前两个字节是0x50 0x4b,那么它很可能是一个zip文件。如果前两个字节是0x1f 0x8b,那么它很可能是一个gzip文件。如果都不是,那么该文件是别的东西。

前两个字节匹配并不能保证它是该类型,但从您的结构中可以看出它通常是一种或另一种,您可以使用扩展名作为进一步证实它已被压缩的证据。

至于不改变位置,您需要一种在不推进位置的情况下查看前两个字节的方法,或者一种获取它们然后取消获取它们以将位置返回到原来的位置的方法。