如何使用JarOutputStream创建JAR文件?

Gil*_*ili 53 java jar

如何使用编程方式创建JAR文件java.util.jar.JarOutputStream?我的程序生成的JAR文件看起来是正确的(它提取正常)但是当我尝试从中加载库时,Java抱怨它无法找到明确存储在其中的文件.如果我提取JAR文件并使用Sun的jar命令行工具重新压缩它,则生成的库可以正常工作.简而言之,我的JAR文件有问题.

请解释如何以编程方式创建JAR文件,并使用清单文件.

Gil*_*ili 93

事实证明,这JarOutputStream有三个未记载的怪癖:

  1. 目录名称必须以"/"斜杠结尾.
  2. 路径必须使用'/'斜杠,而不是'\'
  3. 条目不能以"/"斜杠开头.

以下是创建Jar文件的正确方法:

public void run() throws IOException
{
  Manifest manifest = new Manifest();
  manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
  JarOutputStream target = new JarOutputStream(new FileOutputStream("output.jar"), manifest);
  add(new File("inputDirectory"), target);
  target.close();
}

private void add(File source, JarOutputStream target) throws IOException
{
  BufferedInputStream in = null;
  try
  {
    if (source.isDirectory())
    {
      String name = source.getPath().replace("\\", "/");
      if (!name.isEmpty())
      {
        if (!name.endsWith("/"))
          name += "/";
        JarEntry entry = new JarEntry(name);
        entry.setTime(source.lastModified());
        target.putNextEntry(entry);
        target.closeEntry();
      }
      for (File nestedFile: source.listFiles())
        add(nestedFile, target);
      return;
    }

    JarEntry entry = new JarEntry(source.getPath().replace("\\", "/"));
    entry.setTime(source.lastModified());
    target.putNextEntry(entry);
    in = new BufferedInputStream(new FileInputStream(source));

    byte[] buffer = new byte[1024];
    while (true)
    {
      int count = in.read(buffer);
      if (count == -1)
        break;
      target.write(buffer, 0, count);
    }
    target.closeEntry();
  }
  finally
  {
    if (in != null)
      in.close();
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这些'怪癖'实际上是zip规范的一部分(jar文件只是带有清单和不同扩展名的zip文件).我同意它应该在API文档中记录,但是 - 我建议打开一个问题(http://bugs.sun.com/bugdatabase/) (18认同)
  • 更重要的是,如果您传入错误类型的斜杠或自动转换它们,API应该通过抛出异常来阻止您创建无效的ZIP/JAR文件.对于以斜杠结尾的目录,应该明确记录,因为无法自动更正它.我提交了一份错误报告,但尚未被接受. (5认同)
  • 仅供参考 - 邮政编码规范:http://www.pkware.com/documents/casestudies/APPNOTE.TXT - 搜索“文件名:(变量)”。 (2认同)

小智 10

还有一个需要注意的"怪癖":所有JarEntry的名字都不应以"/"开头.

例如:清单文件的jar条目名称是"META-INF/MANIFEST.MF"而不是"/META-INF/MANIFEST.MF".

所有jar条目都应遵循相同的规则.