Подтвердить что ты не робот

Обновите файл внутри JAR в определенном каталоге с помощью команды 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 может подняться вверх до 2 ГБ, поэтому требуется некоторое время, чтобы сделать это просто, в основном, добавить небольшой ресурс файл для моего гигантского JAR.

Любая помощь по этому поводу очень ценится!

4b9b3361

Ответ 1

4129445: API для инкрементного обновления ZIP файлов в базе данных ошибок Sun/Oracle просит эту функцию реализовать в java-api.

Из оценки:

"Легко сочувствовать тем, кто исправляет эту ошибку. Возможно, легче сочувствовать тем, у кого есть непреднамеренно перезаписанные файлы JAR, которые уже используются JVM."

и

"Было бы неплохо, если бы API-интерфейсы jar и zip разрешали использовать изменяемые zip файлы с первого дня. Но на данный момент добавление изменчивости к jar и zip файлам из Java (или, скорее, к облегчению их мутации) вероятно, приведет к более сложным задачам."

Ответ 2

1. Извлечение одного файла:
Рассмотрим банку со следующим содержанием

$ 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. Обновление одного файла

  • Изменить извлеченный файл
  • обновить банку, используя флаг 'u'. Предоставьте корневой каталог взорванных каталогов, и 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 в комплекте с JDK 7 на Fedora 17.


Я проверил все этапы, упомянутые здесь. Надеюсь, это поможет.

Ответ 3

В этом предыдущем обсуждении показан некоторый исходный код Java для обновления файла zip (или jar).

Мне не совсем ясно, будет ли это на самом деле быстрее, чем с помощью jar -u, но по крайней мере вы должны иметь возможность адаптировать этот код, чтобы вам не пришлось воссоздавать файловую структуру на диске.

Изменить: Вот документация в утилите "jar" - вы сами можете убедиться, что конкретное поведение, которое вы ищете ибо, хотя это было бы полезно, его там нет.

Я думаю, что причина в том, что интерфейс командной строки в основном является клоном команды "tar" Unix/Linux. Конечно, он создает формат zip, а не tar.

Edit # 2 - Мне пришло в голову, что для добавления файла в zip вам просто нужно отключить центральный каталог с конца файла, добавить новую запись, а затем перезаписать центральную каталог. Обновление будет одним и тем же, за исключением того, что вместо добавления записи в каталог вы должны обновить существующую запись каталога, чтобы указать на новую запись zip.

Изучая эту возможность, я обнаружил, что Java 7 включает поставщик zip файловой системы, который выглядит так, как будто он делает это, и может сформировать основу решения для того, что вы хотите сделать.

Ответ 4

Я думаю, это связано с тем, как работают классы в пакете java.util.zip. Они сидят поверх потоков.

Класс ZipFile построен поверх ZipFileInputStream. Запись zip файлов выполняется путем подачи ZipEntries один за другим в ZipOutputStream.

Я предполагаю, что исполняемый файл jar построен поверх этих классов.

Ответ 5

Я тоже пытался обновить банку, не воспроизводя структуру jar файла, внешнюю к банке, и по какой-то причине jar uf jarFileName -C... команда никогда не позволяла мне копировать файл в дочерний каталог в банке. Затем я попытался разрезать и вставить файл в банку, используя ubuntu 14.04, встроенный в диспетчер архива (т.е. Щелкнуть правой кнопкой мыши по файлу jar и выбрать "открыть с помощью менеджера архива", а затем вставить файл в любом месте в файловой структуре jar), и он сработал. Это не решение cli, но оно работает. Надеюсь, это поможет кому-то еще некоторое время.

Ответ 6

Это работает, но это не исчерпывающее решение, на которое вы смотрите.

Вместо того, чтобы вручную создавать структуру папок, я прошу указать весь путь, поэтому 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%