【问题标题】:How to identify a zip file in java?如何在java中识别一个zip文件?
【发布时间】:2016-02-29 06:51:56
【问题描述】:

我想识别我的存档是zip 还是rar。但是问题是在我验证文件之前出现运行时错误。我想创建自定义通知:

public class ZipValidator {
  public void validate(Path pathToFile) throws IOException {
    try {
      ZipFile zipFile = new ZipFile(pathToFile.toFile());
      String zipname = zipFile.getName();
    } catch (InvalidZipException e) {
      throw new InvalidZipException("Not a zip file");
    }
  }
}

目前我有运行时错误:

java.util.zip.ZipException:打开 zip 文件时出错

【问题讨论】:

  • 获取文件名。用 . 分割文件名。并获得扩展。检查扩展名是rar还是zip。
  • @Ravindrababu - 是什么阻止了简单地将非 zip 文件的扩展名更改为 zip 或 rar?

标签: java archive identification


【解决方案1】:

我建议打开一个普通的 InputStream 并读取前几个字节(魔术字节),而不是依赖文件扩展名,因为这很容易被欺骗。此外,您可以省略创建和解析文件的开销。

对于 RAR,第一个字节应该是 52 61 72 21 1A 07

对于 ZIP,它应该是以下之一:

  • 50 4B 03 04
  • 50 4B 05 06(空存档)
  • 50 4B 07 08(跨区存档)。

来源:https://en.wikipedia.org/wiki/List_of_file_signatures

还有一点,刚刚看了你的代码:

为什么你会捕捉到 InvalidZipException,把它扔掉并构造一个新的?这样一来,您就会丢失原始异常中的所有信息,从而难以调试和理解究竟出了什么问题。要么根本不抓住它,要么,如果你必须把它包起来,那就做对吧:

} catch (InvalidZipException e) {
  throw new InvalidZipException("Not a zip file", e);
}

【讨论】:

    【解决方案2】:

    合并 nanda 和 bratkartoffel 的答案。

    private static boolean isArchive(File f) {
        int fileSignature = 0;
        try (RandomAccessFile raf = new RandomAccessFile(f, "r")) {
            fileSignature = raf.readInt();
        } catch (IOException e) {
            // handle if you like
        }
        return fileSignature == 0x504B0304 || fileSignature == 0x504B0506 || fileSignature == 0x504B0708;
    }
    

    【讨论】:

    • 最好使用 InputStream,因为它处理的是更一般的输入,不是吗?
    【解决方案3】:
    RandomAccessFile raf = new RandomAccessFile(f, "r");
    
    long n = raf.readInt();
    
    raf.close();
    
    if (n == 0x504B0304)
    
        System.out.println("Should be a zip file");
    
    else
    
        System.out.println("Not a zip file");
    

    您可以在以下链接中看到它。 http://www.coderanch.com/t/381509/java/java/check-file-zip-file-java

    【讨论】:

    • 部分正确,可以有 3 个不同的签名,而不仅仅是一个。
    【解决方案4】:

    异常抛出

    ZipFile zipFile = new ZipFile(pathToFile.toFile());
    

    这是因为如果将非 ZipFile 作为 ZipFileconstructor 的参数给出,则会抛出 ZipException。 因此,如果您的文件路径指向正确的ZipFile,则必须在生成新的ZipFile 对象之前检查。 一种解决方案可能是像这样检查文件路径的扩展名

     PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:*.zip");
     boolean extensionCorrect = matcher.matches(path); 
    

    【讨论】:

      【解决方案5】:

      添加到对话中。

      在 Java 8 中,有一个名为 Files.probeContentType(Path path) 的方法应该也可以工作。

      这是一个例子:

      String contentType = Files.probeContentType(Paths.get(pathToFile);
      
      if (!contentType.equals("application/zip")) {
      
          throw new NotZipFileException();
      }
      

      【讨论】:

      • probe 有点夸大其词:内容通常被忽略,标准实现似乎着眼于文件扩展名或文件系统设置。有时可能有用,但这不是我想要的!
      猜你喜欢
      • 1970-01-01
      • 2010-11-08
      • 1970-01-01
      • 1970-01-01
      • 2020-01-11
      • 1970-01-01
      • 2012-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多