如何在不保存到磁盘的情况下将JarInputStream转换为Jar文件?

时间:2011-04-27 12:02:40

标签: java jar

我有一个Servlet,用户可以在其上传.jar文件以检查其MANIFEST.MF

我知道以下内容可行:

JarInputStream in = new JarInputStream(new ByteArrayInputStream (fileItem.get()));
Manifest mf = in.getManifest(); 

不幸的是getManifest()方法解析Key:Value并需要“:”(冒号+空格),一个简单的冒号是不够的。由于我正在使用的手机也工作,如果MANIFEST.MF只有冒号而不是冒号+空格,我想手动提取MANIFEST.MF,但我不想保存文件磁盘。

如果我有一个JarFile,我可以通过以下方式解析清单:

JarFile jarFile = new JarFile(fileName);
InputStream in = jarFile.getInputStream(jarFile.getEntry("META-INF/MANIFEST.MF"));
BufferedReader br = new BufferedReader(new InputStreamReader(in));

String line;
while ((line = br.readLine()) != null) {
    String[] splitAr = line.split(":", 0);
    // ...

但遗憾的是,我不知道如何将JarInputStream(或ByteArrayInputStream)转换为JarFile

4 个答案:

答案 0 :(得分:4)

在这种情况下我会尝试做什么:

  • 使用getNextEntry() - 而不是getNextJarEntry()遍历jar中的所有条目!看看你能否以这种方式达到清单
  • 尝试使用更为通用的ZipInputStream - JarInputStream实际上扩展了它 - 这应该可以让您获取META-INF/MANIFEST.MF文件。

答案 1 :(得分:2)

标准API不支持此功能。构造JarFile的唯一方法是提供File引用,并且由于API不提供用于创建由例如InputStream支持的“特殊文件”的接口,因此无法解决它

如果您使用的是UNIX系统,则可能会设置device file一些方法,但会丢失可移植性。

答案 2 :(得分:0)

  private static void copyFiles(JarInputStream in, JarOutputStream out)
    throws IOException
  {
    JarEntry inEntry;
    byte[] buffer = new byte[4096];

    while ((inEntry=(JarEntry)in.getNextEntry())!=null)
          {if (inEntry.getMethod()==0)
              {out.putNextEntry(new JarEntry(inEntry));
              }
           else
               {out.putNextEntry(new JarEntry(inEntry.getName()));
               }
           //InputStream data=in;//the call to ZipInputStream.getNextEntry() positions the InputStream at the start of the entry and therefore supplying the ZipInputStream is the equivalent of supplying a ZipEntry's InputStream.the ZipInputStream is smart enough to handle the entry's EOF downstream
           int num;
           while ((len=/*data*/in.read(buffer))>0)
                 {out.write(buffer, 0, len);
                 }
           out.flush();
          }
  }

答案 3 :(得分:0)

您可以将输入流中的清单作为字符串读取,并自行解析

/**
 * Read JAR  manifest as String from input stream.
 * Like JarInputStream, assume that META-INF/MANIFEST.MF entry  should be either 
 * the first or the second entry (when preceded  by the dir META-INF/).
 */
def readManifestAsString(InputStream is) {
    def zip = new ZipInputStream(is);
    def e = zip.getNextEntry();
    if (e != null && e.getName().equalsIgnoreCase("META-INF/"))
        e =  zip.getNextEntry();  
    if (e != null && JarFile.MANIFEST_NAME.equalsIgnoreCase(e.getName())) {
        byte[] bytes = getBytes(new BufferedInputStream(zip));
        return new String(bytes, "UTF8");
     }
}

byte[] getBytes(InputStream is) {
        byte[] buffer = new byte[8192];
        ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
        int n;
        while ((n = is.read(buffer, 0, buffer.length)) != -1) {
            baos.write(buffer, 0, n);
        }
        return baos.toByteArray();
 }

可以找到JAR Manifest规范here