使用jar命令更新特定目录中JAR内的文件

时间:2012-12-05 18:09:16

标签: java jar

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

问题是我想在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所以这需要一段时间来做到这一点,基本上,添加一点资源提交给我巨大的JAR。

非常感谢任何帮助!

6 个答案:

答案 0 :(得分:47)

正如已接受的答案已经指出的那样,您不能同时使用zipjar命令将文件系统上的特定文件插入特定文件压缩文件中的目录。

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

<强> 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将更新其下的所有路径元素。
  3. 示例:

    $ 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?

    我在Fedora 17上使用了与JDK 7捆绑在一起的jar


    我已经验证了此处提到的所有步骤。希望这会有所帮助。

答案 1 :(得分:5)

Sun / Oracle错误数据库中的

4129445 : An API to incrementally update ZIP files要求在java api中实现此功能。

来自评估:

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

“如果jar&amp; zip API从第一天开始就允许使用可变的zip文件就好了。但是在这一点上增加了来自Java的jar和zip文件的可变性(或者更确切地说,增加了改变它们的容易性)似乎可能会引入更多难以调试的问题。“

答案 2 :(得分:1)

This previous discussion显示了一些用于更新zip(或jar)文件的Java源代码。

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

在'jar'实用程序上编辑:Here is the documentation - 您可以自己查看您正在寻找的特定行为,虽然它很有用但不存在。

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

编辑#2 - 我想到要将文件添加到zip中,您只需要从文件末尾删除中心目录,附加新条目,然后重写中心目录。更新将是相同的,除了不是将条目添加到目录,您将更新现有的目录条目以指向新的zip条目。

在探索这种可能性时,我发现Java 7包含一个zip file system provider,看起来就是这样,并且可以构成您想要做的解决方案的基础。

答案 3 :(得分:1)

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

ZipFile类构建在ZipFileInputStream之上。 编写zipfiles是通过将ZipEntries逐个送入ZipOutputStream来完成的。

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

答案 4 :(得分:0)

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

答案 5 :(得分:-2)

它有效,但它不是你正在寻找的extact解决方案。

而不是手动创建文件夹结构,我要求提及整个路径,所以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%