Почему невозможно удалить записи из файла JAR? - PullRequest
5 голосов
/ 15 июня 2010

Можно добавить новые записи в файл jar с помощью инструмента jar.
Можно изменить некоторые записи в файле jar с помощью инструмента jar.
Но невозможно удалить некоторые записи из файла JAR.
Почему?

Ответы [ 6 ]

4 голосов
/ 22 августа 2014

Никто действительно не ответил на оригинальный вопрос Why?, ответы просто содержат советы, как все еще это сделать.

Так почему?

Файлы jar и zip представляют собой сжатые файлы, имеющие набор файловили директора, обычно называемые записи .Структура / формат файлов jar / zip - это последовательное перечисление записей (кроме заголовка формата файла zip).

Каждая запись имеет заголовок, который содержит информацию о записи, например, ееимя, тип, его длина в байтах (и другие).

Теперь, взяв этот последовательный список записей, как бы вы удалили запись из середины файла?Это оставило бы "дыру" в середине файла.Единственный способ удалить запись (без необходимости повторного создания архива без удаляемой записи) - это скопировать содержимое файла zip, начиная с записи, до начала текущей (удаляемой) записи, а также обрезать файл zip.длина по длине удаленной записи.

Представьте, что это будет означать, если у вас есть архив с десятками или сотнями МБ?Если вы удалите запись в начале, вам придется скопировать почти все содержимое файла на несколько байт (или килобайт) назад, чтобы не оставить пробел в файле.

Так вот почему.

Эта структура позволяет легко добавлять новые записи, потому что их можно легко добавлять в конец файла, но удаление (запись) не может быть эффективно выполнено.

3 голосов
/ 15 июня 2010

Цель файла jar - упаковать приложение Java.Нет необходимости удалять записи, так как вы упаковываете приложение для развертывания.

Вот три возможных способа сделать это.

  1. Вы можете использовать winzip или какой-либо другой zipУтилита
  2. Вы можете просто использовать банку с соответствующими записями (Удалить банку и переупаковку).
  3. Вы можете сделать это программно ...

...вроде, см. ниже:

import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.util.jar.*;


public class JarUpdate
{
    /**
     * main()
     */
    public static void main(String[] args) throws IOException
    {
        // Get the jar name and entry name from the command-line.

        String jarName = args[0];
        String fileName = args[1];

        // Create file descriptors for the jar and a temp jar.

        File jarFile = new File(jarName);
        File tempJarFile = new File(jarName + ".tmp");

        // Open the jar file.

        JarFile jar = new JarFile(jarFile);
        System.out.println(jarName + " opened.");

        // Initialize a flag that will indicate that the jar was updated.

        boolean jarUpdated = false;

        try
        {
            // Create a temp jar file with no manifest. (The manifest will
            // be copied when the entries are copied.)

            Manifest jarManifest = jar.getManifest();
            JarOutputStream tempJar = new JarOutputStream(new FileOutputStream(tempJarFile));

            // Allocate a buffer for reading entry data.

            byte[] buffer = new byte[1024];
            int bytesRead;

            try
            {
                // Open the given file.

                FileInputStream file = new FileInputStream(fileName);

                try
                {
                    // Create a jar entry and add it to the temp jar.

                    JarEntry entry = new JarEntry(fileName);
                    tempJar.putNextEntry(entry);

                    // Read the file and write it to the jar.

                    while ((bytesRead = file.read(buffer)) != -1)
                    {
                        tempJar.write(buffer, 0, bytesRead);
                    }

                    System.out.println(entry.getName() + " added.");
                }
                finally
                {
                    file.close();
                }

                // Loop through the jar entries and add them to the temp jar,
                // skipping the entry that was added to the temp jar already.

                for (Enumeration entries = jar.entries(); entries.hasMoreElements();)
                {
                    // Get the next entry.

                    JarEntry entry = (JarEntry)entries.nextElement();

                    // If the entry has not been added already, add it.

                    if (!entry.getName().equals(fileName))
                    {
                        // Get an input stream for the entry.

                        InputStream entryStream = jar.getInputStream(entry);

                        // Read the entry and write it to the temp jar.

                        tempJar.putNextEntry(entry);

                        while ((bytesRead = entryStream.read(buffer)) != -1)
                        {
                            tempJar.write(buffer, 0, bytesRead);
                        }
                    }
                }

                jarUpdated = true;
            }
            catch (Exception ex)
            {
                System.out.println(ex);

                // Add a stub entry here, so that the jar will close without an
                // exception.

                tempJar.putNextEntry(new JarEntry("stub"));
            }
            finally
            {
                tempJar.close();
            }
        }
        finally
        {
            jar.close();
            System.out.println(jarName + " closed.");

            // If the jar was not updated, delete the temp jar file.

            if (!jarUpdated)
            {
                tempJarFile.delete();
            }
        }

        // If the jar was updated, delete the original jar file and rename the
        // temp jar file to the original name.

        if (jarUpdated)
        {
            jarFile.delete();
            tempJarFile.renameTo(jarFile);
            System.out.println(jarName + " updated.");
        }
    }
}
2 голосов
/ 16 июня 2010

Почему?

Возможно, поскольку команда jar похожа на команду tar unix.Оба предназначены для создания архивов и не предназначены для управления ими.

Альтернативы:

  • Если вам нужно вертеть вручную, просто используйте инструмент, например 7-zip .
  • Если вы хотите (пере) создать jar-файл программно ant ваш друг
1 голос
/ 22 февраля 2013

Просто чтобы быть полным.

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

Если банка подписана, не забудьте удалить подпись и оставить ее в покое

0 голосов
/ 11 августа 2017

Это не невозможно.Вы можете сделать это с помощью любой zip-утилиты.

Вы просто не можете сделать с помощью команды jar.

0 голосов
/ 03 февраля 2014

Использовать команды cmd - zip -d c: /path/path/file.jar path / path / file.XMLSchema

пример на Java http://www.mkyong.com/java/how-to-execute-shell-command-from-java/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...