34

所以我一直在寻找这个答案的高低,显然还没有找到一个令人满意的答案。

问题是我想更新 JAR 中的 JAR(或任何文件),但所述文件位于文件夹结构内,我想避免在 JAR 外部复制,以便我可以更新它。

例子:

Foo.jar (root directory)
/
|->/folder1
|
|->/folder2
|
|->/foo
    |
    |-->/bar
         |
         |---->/baz
               |
               |------>file_to_update.jar

所以,如果我想使用jar命令更新它,我必须首先在 JAR 之外创建相同的文件夹结构,然后执行

jar -uf Foo.jar -C foo/bar/baz/file_to_update.jar

但是我想避免创建这个文件夹结构,因为对于某些文件它可能很深,而且我可能需要更新整个容器 JAR 中的选定文件,所以我不想创建这么多具有​​特定结构的文件夹所以jar命令可以更新它们。

换句话说,我想告诉jar命令使用特定源目录中的特定源文件更新特定目标目录中的特定目标文件。

即类似的东西

jar -uf Foo.jar -sourceFile /x/y/z/filetoupdate -destFile /a/b/c/filetoupdate 

(我知道这种语法不起作用,它只是为了举例说明我需要什么)。

这可以做到吗?当jar命令可以找到它的匹配项或其他东西时,我绝对需要模仿整个文件夹结构,这让我感到非常奇怪,因为我可能需要更新 100 个文件夹深的文件夹结构中的文件. 仅仅为了更新文件而重现过于复杂。

另外,我知道可以使用常规的 ZIP 实用程序,但是我在 Linux 中可用的那个没有更新文件,即使它说它更新了(重新打开 jar 后,它的旧版本完好无损),现在我不能去寻找另一个(公司政策,没有时间,测试问题,你的名字)。

最后,如果我可以从命令行执行此操作,这意味着我可以创建一个批处理文件来更新大量特定文件,而无需创建文件夹结构。

我忘了说我也想避免解压缩、更新、重新压缩整个东西,因为这个 JAR 可以上升到 2GB,所以这样做需要一段时间,基本上,添加一个小资源文件到我的巨大的罐子。

非常感谢您对此的任何帮助!

4

6 回答 6

53

正如公认的答案已经指出的那样,您既不能使用 thezip也不能使用jar命令将文件系统上的特定文件插入到压缩文件内的特定目录中。

但是有一个解决方法,简而言之,它首先在压缩文件中提取特定文件,您可以对其进行更新,然后将其放回压缩文件中:

1.提取单个文件:
考虑一个具有以下内容的jar

$ jar tvf foo.jar 
 0 Thu Jan 10 00:05:06 IST 2013 META-INF/
68 Thu Jan 10 00:05:06 IST 2013 META-INF/MANIFEST.MF
 0 Thu Jan 10 00:04:30 IST 2013 x/
 0 Thu Jan 10 00:07:36 IST 2013 x/b/
 9 Thu Jan 10 00:07:36 IST 2013 x/b/hello.txt
 0 Thu Jan 10 00:04:30 IST 2013 x/a/

要仅提取 hello.txt,您必须提供要提取的文件的完全限定路径。Jar 也会创建适当的文件夹。

例子 :

$ jar xvf foo.jar x/b/hello.txt
inflated: x/b/hello.txt

$ tree x/
x
└── b
    └── hello.txt  
1 directory, 1 file

2.更新单个文件

  1. 修改解压文件
  2. 使用 'u' 标志更新 jar。提供展开的目录 root 和 jar 应更新其下的所有路径元素。

例子:

$ jar vfu foo.jar x/
adding: x/(in = 0) (out= 0)(stored 0%)
adding: x/b/(in = 0) (out= 0)(stored 0%)
adding: x/b/hello.txt(in = 23) (out= 11)(deflated 52%)

3. 我用的是哪个版本的 jar?

jar在 Fedora 17 上与 JDK 7 捆绑使用。


我已经验证了这里提到的所有步骤。希望这可以帮助。

于 2013-01-09T19:03:36.220 回答
4

4129445:用于增量更新Sun/Oracle 错误数据库中的 ZIP 文件的 API 要求在 java api 中实现此功能。

从评价:

“很容易同情那些希望修复这个错误的人。同情那些无意中覆盖了已经被正在运行的 JVM 使用的 JAR 文件的人也许更容易同情。”

“如果 jar 和 zip API 从一开始就允许可变的 zip 文件,那就太好了。但是在这一点上,从 Java 中为 jar 和 zip 文件增加可变性(或者更确切地说,增加改变它们的便利性)似乎可能会引入更难调试的问题。”

于 2013-01-13T20:43:53.410 回答
1

前面的讨论显示了一些用于更新 zip(或 jar)文件的 Java 源代码。

我并不完全清楚这是否真的比 using 更快jar -u,但至少您应该能够调整该代码,这样您就不必在磁盘上重新创建文件结构。

编辑:这是关于“jar”实用程序的文档 - 您可以自己查看您正在寻找的特定行为,虽然它很有用,但不存在。

我认为原因是命令行界面基本上是 Unix/Linux 'tar' 命令的克隆。当然,它生成的是 zip 格式,而不是 tar。

编辑 #2 - 我想到要将文件添加到 zip,您只需从文件末尾剥离中央目录,附加新条目,然后重新写入中央目录。更新将是同样的事情,除了将条目添加到目录之外,您将更新现有目录条目以指向新的 zip 条目。

在探索这种可能性时,我发现 Java 7 包含一个zip 文件系统提供程序,看起来它可以做到这一点,并且可以构成您想要做的解决方案的基础。

于 2013-01-09T03:23:40.637 回答
1

我认为这是由于 java.util.zip 包中的类是如何工作的。他们坐在溪流之上。

ZipFile类建立在 ZipFileInputStream 之上。编写 zipfile 是通过将 ZipEntries 逐个提供给 ZipOutputStream 来完成的。

我假设 jar 可执行文件是建立在这些类之上的。

于 2013-01-13T19:54:23.013 回答
0

我也试图在不复制 jar 外部的 jar 文件结构的情况下更新 jar,并且由于某种原因jar uf jarFileName -C ... 命令永远不会让我将文件复制到 jar 中的子目录。然后我尝试使用 ubuntu 14.04 的内置存档管理器将文件剪切并粘贴到 jar 中(即右键单击 jar 文件并选择“使用存档管理器打开”,然后将文件粘贴到 jar 文件结构中的任何位置),它工作. 这不是一个 cli 解决方案,但它可以工作。希望这可以节省其他人一些时间。

于 2016-09-08T14:35:35.850 回答
-2

它有效,但它不是您正在查看的确切解决方案。

我要求提及整个路径,而不是手动创建文件夹结构,因此 mkdir 也会创建文件夹和子目录。希望这会有所帮助....

set /p Folder=where you want to move inside jar 
set /p File=Mention path of file to be moved 
set /p Jarfile=Where is your jar file
mkdir %Folder%
copy %File% %Folder%
jar -uvf %Jarfile% %File%
rd /s /q %Folder%
rmdir %Folder%
于 2017-07-20T06:04:06.647 回答