【问题标题】:How to read a jar file, convert it to a string and create a new jar file from that string?如何读取 jar 文件,将其转换为字符串并从该字符串创建新的 jar 文件?
【发布时间】:2014-04-26 16:45:56
【问题描述】:

我正在尝试为 OSGi 包实现一些“无线”更新机制。为此,我需要能够从字符串创建一个 jar 文件(基本上是 JarInputStream 读取的 jar 文件的内容)。下面的示例代码应该能说明我的需求:

                //read bundle to be copied!
                File originalFile = new File(
                        "/Users/stefan/Documents/Projects/OSGi/SimpleBundle_1.0.0.201404.jar");
                JarInputStream fis = new JarInputStream(new FileInputStream(originalFile));
                StringBuilder stringBuilder = new StringBuilder();
                int ch;
                while ((ch = fis.read()) != -1) {
                    stringBuilder.append((char) ch);
                }

                fis.close();

                //Create content string
                String content = stringBuilder.toString();
                if (logger.isInfoEnabled()) {
                    logger.info(content);
                }

                //Init new jar input stream
                JarInputStream jarInputStream = new JarInputStream(
                        new ByteArrayInputStream(content.getBytes()));

                if (logger.isInfoEnabled()) {
                    logger.info("Save content to disc!");
                }

                File newFile = new File(
                        "/Users/stefan/Documents/Projects/OSGi/equinox/SimpleBundle_1.0.0.201404.jar");
                //Init new jar output stream
                JarOutputStream fos = new JarOutputStream(
                        new FileOutputStream(newFile));

                if (!newFile.exists()) {
                    newFile.createNewFile();
                }

                int BUFFER_SIZE = 10240;
                byte buffer[] = new byte[BUFFER_SIZE];

                while (true) {

                    int nRead = jarInputStream.read(buffer, 0,
                            buffer.length);
                    if (nRead <= 0)
                        break;

                    fos.write(buffer, 0, nRead);
                }

                //Write content to new jar file.
                fos.flush();
                fos.close();
                jarInputStream.close();

不幸的是,创建的 jar 文件是空的,如果我尝试使用 JD-GUI 打开它会引发“输入文件无效”错误。是否可以从字符串“内容”创建一个 jar 文件?

最好的问候,非常感谢你 斯蒂芬

【问题讨论】:

  • 看起来您的代码的意图基本上是将字节/字符从一个文件复制到另一个文件。在那种情况下,是否需要通过 JarInputStream 等传递它?你不能只复制文件吗?
  • 我的意图是使用 OSGi Bundle API 来更新某个包。为此,我需要下载新的 jar 文件,将其保存到光盘中,然后调用 update 方法并交出该新 jar 文件的输入流。
  • 但除非我遗漏了什么,否则上面代码的最终结果就是保存在磁盘上的文件(目前是零长度,对吧?)。所以你不能把字节保存到磁盘上,简化上面的代码吗? (例如,如果它是一个压缩的 jar,您当前正在将其解压缩到内存中,然后将其重新压缩到磁盘。)简化的代码可能更容易找到您的问题(或者问题可能会消失!)然后获取 InputStream 并传递它更新()将是下一步。 (顺便说一下,我假设您在日志中看到了您期望的日志语句?)
  • 另外,1) FileOutputStream 有一个构造函数,允许您传递文件名,如果文件名不存在,它应该创建它,2) 您是否在 while (true) 循环中调试或插入打印并且正在从 jarInputStream 中读取已确认的内容,3) 如果是这样,如何暂时取出 JarOutputStream 并仅使用 FileOutputStream 来检查您是否获得了非空文件?
  • 也感谢蒂姆,你们帮了我很多。

标签: java jar osgi


【解决方案1】:

您的 jar 是空的,因为您没有从 JarInputStream 中读取任何内容。如果你想阅读 JarInputStream,你应该迭代它的条目。如果要改变Manifest,第一个条目要跳过,使用jarInputStream的getManifest()和JarOutputStream的构造函数,这里可以指定Manifest。基于您的代码(没有清单更改,但普通的 jar 副本):

ZipEntry zipEntry = jarInputStream.getNextEntry();
while (zipEntry != null) {
    fos.putNextEntry(zipEntry);

    // Simple stream copy comes here
    int BUFFER_SIZE = 10240;
    byte buffer[] = new byte[BUFFER_SIZE];
    int l = jarInputStream.read(buffer);
    while(l >= 0) {
        fos.write(buffer, 0, l);
        l = jarInputStream.read(buffer);
    }

    zipEntry = jarInputStream.getNextEntry();
}

仅当您想在复制过程中更改 JAR 文件的内容(清单或条目)时才需要它。否则,简单的 InputStream 和 FileOutputStream 将完成工作(正如 Tim 所说)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    相关资源
    最近更新 更多