web-dev-qa-db-fra.com

Mettre à jour un fichier dans un fichier JAR d'un répertoire spécifique à l'aide de la commande jar

J'ai donc cherché haut et bas une réponse à cette question et, bien évidemment, je n'ai pas trouvé de réponse satisfaisante.

Le problème est que je veux mettre à jour un fichier JAR (ou n'importe quel fichier) à l'intérieur d'un fichier JAR, mais que ce fichier se trouve dans une structure de dossiers, ce que je ne voudrais pas reproduire en dehors du fichier JAR afin de pouvoir le mettre à jour.

Exemple:

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

Donc, si je veux mettre à jour ceci en utilisant la commande jar , je devrais d’abord créer la même structure de dossiers en dehors du JAR, puis faire.

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

Toutefois, je voudrais éviter de créer cette structure de dossiers car, pour certains fichiers, cela peut être assez profond et aussi parce que je pourrais avoir besoin de mettre à jour des fichiers sélectionnés dans le JAR du conteneur, je ne voudrais donc pas créer autant de dossiers avec une structure spécifique. pour que la commande jar puisse les mettre à jour.

En d'autres termes, je voudrais dire à la commande jar de mettre à jour un fichier de destination spécifique dans un répertoire de destination spécifique, en utilisant un fichier source spécifique dans un répertoire source spécifique.

C'est à dire. quelque chose comme 

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

(Je sais que cette syntaxe ne fonctionne pas, c'est juste pour illustrer ce dont j'ai besoin).

Cela peut-il être fait? Cela me semblerait très étrange que je devrais absolument imiter la structure de dossiers entière lorsque la commande jar pourrait trouver une correspondance, ou quelque chose, car je pourrais avoir besoin de mettre à jour un fichier dans une structure de dossiers qui est 100 dossiers profonds. Ce serait trop complexe à reproduire juste pour mettre à jour le fichier.

De plus, je sais qu’un utilitaire Zip standard pourrait être utilisé, mais celui que j’ai disponible sous Linux ne met pas à jour le fichier même s’il le dit (lors de la réouverture du fichier jar, l’ancienne version est intacte), et pour le moment Je ne peux pas en chercher un autre (politique de l'entreprise, pas de temps, problèmes de test, vous l'appelez).

Enfin, si je peux le faire depuis une ligne de commande, cela signifie que je peux créer un fichier de commandes pour mettre à jour de nombreux fichiers spécifiques sans avoir à créer la structure de dossiers.

J'ai oublié de dire que je voudrais aussi éviter de devoir unjar, mettre à jour, rejeter le tout, car ce fichier JAR peut aller jusqu'à 2 Go, il faut donc un peu de temps pour le faire, simplement pour ajouter un petit fichier de ressources à mon ordinateur. JAR gigantesque.

Toute aide à ce sujet est grandement appréciée!

27
Acapulco

4129445: Une API pour mettre à jour de manière incrémentielle les fichiers Zip dans la base de données de bogues Sun/Oracle, demande que cette fonctionnalité soit implémentée dans l'API Java.

De l'évaluation:

"Il est facile de sympathiser avec ceux qui veulent que ce bogue soit corrigé. C'est peut-être plus facile de sympathiser avec ceux qui ont, par inadvertance, écrasé des fichiers JAR déjà utilisés par une JVM en cours d'exécution."

et

"Cela aurait été agréable si les API jar & Zip avaient permis les fichiers Zip mutables dès le premier jour. Mais à ce stade, ajouter de la mutabilité aux fichiers jar & Zip à partir de Java (ou au contraire, augmenter la facilité de leur mutation) semble présenter plus de problèmes de débogage ".

5
flup

Comme la réponse acceptée l'a déjà indiqué, vous ne pouvez utiliser ni la commande Zip ni la commande jar pour insérer un fichier spécifique sur le système de fichiers dans un répertoire spécifique du fichier compressé.

Mais il y a cette solution de contournement} _ qui, en résumé, extrait d'abord un fichier spécifique à l'intérieur du fichier compressé, vous pouvez le mettre à jour, puis le replacer dans le fichier compressé:

1. Extraire un seul fichier:
Considérons un pot avec le contenu suivant 

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

Pour extraire uniquement hello.txt, vous devez indiquer le chemin complet du fichier à extraire. Jar crée également des dossiers appropriés.

Exemple : 

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

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

2. Mise à jour d'un seul fichier _

  1. Modifier le fichier extrait
  2. mettre à jour le pot en utilisant le drapeau 'u'. Fournissez le répertoire éclaté root et jar mettra à jour tous les éléments de chemin situés en dessous.

Exemple:

$ 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. Avec quelle version de jar j'ai essayé cela?} _

J'ai utilisé jar fourni avec JDK 7 sur Fedora 17.


J'ai vérifié toutes les étapes mentionnées ici. J'espère que cela t'aides.

45
Amit Sharma

Cette discussion précédente montre du code source Java pour la mise à jour d'un fichier Zip (ou jar).

Je ne sais pas vraiment si cela sera réellement plus rapide que d'utiliser jar -u, mais au moins, vous devriez pouvoir adapter ce code pour ne pas avoir à recréer la structure de fichier sur le disque. 

Edit: Voici la documentation sur l'utilitaire 'jar' - vous pouvez constater par vous-même que le comportement particulier que vous recherchez, bien que utile, n'en fait pas partie.

Je pense que la raison en est que l'interface de ligne de commande est fondamentalement un clone de la commande Unix/Linux 'tar'. Bien sûr, il produit un format Zip plutôt que tar.

Edit # 2 - Je me suis dit que pour ajouter un fichier à un fichier Zip, il suffisait d'extraire le répertoire central de la fin du fichier, d'ajouter la nouvelle entrée et de réécrire le répertoire central. Une mise à jour serait la même chose, mais au lieu d’ajouter l’entrée au répertoire, vous mettriez à jour l’entrée de répertoire existante pour pointer vers la nouvelle entrée Zip. 

Lors de l’exploration de cette possibilité, j’ai constaté que Java 7 inclut un fournisseur de système de fichiers Zip , qui ressemble à cela et qui pourrait constituer la base d’une solution à ce que vous voulez faire.

1
GreyBeardedGeek

Je pense que cela est dû à la manière dont les classes du package Java.util.Zip fonctionnent . Elles se trouvent au-dessus des flux.

La classe ZipFile est construite sur un flux ZipFileInputStream . L'écriture de fichiers zip est réalisée en transmettant les ZipEntries un par un à un flux ZipOutputStream.

Je suppose que l'exécutable jar est construit sur ces classes.

1
flup

J'essayais moi aussi de mettre à jour un fichier jar sans reproduire la structure de fichier du fichier jar externe au fichier jar, et pour une raison quelconque, le jar uf jarFileName -C ... commande ne me laisse jamais copier le fichier dans un répertoire enfant du fichier jar. . J'ai ensuite essayé de couper et coller le fichier dans le jar en utilisant le gestionnaire d'archives intégré d'ubuntu 14.04 (c.-à-d. Cliquer avec le bouton droit sur le fichier jar et choisir "ouvrir avec le gestionnaire d'archives" puis coller le fichier n'importe où dans la structure de fichiers du jar), et cela a fonctionné. . Ce n'est pas une solution cli mais ça marche. J'espère que cela sauve du temps à quelqu'un d'autre.

0
ellisbjohns