Главная > Java сниппеты > Работаем с JAR-архивами.

Тема Зацепин
268

Java-разработчик 🧩
37
1 минуту

Работаем с JAR-архивами.

Автор: Роман Воронов

Добавлено : 2 Nov 2008, 14:32

Иногда возникает потребность в том, чтобы java-программа могла просмотреть содержимое jar-архива, и извлечь его. В Интернете мне не удалось найти много информации по этому вопросу. Хотя, если честно, я не очень-то и искал. Поэтому, решил разобраться во всём сам. Пошарив по документации, мне в голову пришли следующие мысли. Если мы заранее знаем, что именно нам нужно извлечь из jar-файла, это не составит особого труда.

  1. Для начала нам нужно создать объект класса java.util.jar.JarFile (далее JarFile), и указать для него имя просматриваемого jar-файла.
  2. Затем, создаём объект класса java.util.jar.JarEntry (далее JarEntry) и указываем для него имя файла, который необходимо извлечь.
  3. Для объекта JarFile создаём поток ввода с помощью метода getInputStream(). В качестве аргумента передадим ему объект JarEntry.
  4. Ну а далее, работаем с потоками стандартным образом, используя методы read() и write().

У нас должно получиться что-то вроде:

JarFile jarFile = new JarFile("some_jar_file.jar");
JarEntry jarEntry =
new JarEntry("something.smth");
InputStream in = jarFile.getInputStream
(jarEntry);
FileOutputStream out =
new FileOutputStream(jarEntry.getName());
int t;
while((t = in.read()) != -1)
out.write(t);

Конечно же не забываем включить обработку исключения IOException. Не правда ли, элементарно? Но что делать, если мы не знаем, что содержится в jar-архиве? Подумав немного над этим вопросом, я ознакомился с классом ZipFile. Ведь JarFile является его наследником. У класса ZipFile есть метод entries(), который возвращает объект интерфейса Enumeration, содержащий имена всех файлов, входящих в архив. Но так как пользоваться этим объектом, мягко говоря, неудобно, то имеет смысл перенести всё содержимое в объект класса Vector. Получаем что-то типа:

Enumeration entries;
Vector v;
int vc=0;
/*
* Vector capacity – количество элементов в векторе v. Почему-то, метод
* v.capacity() выдаёт большее число, чем на самом деле. Разбираться с этим не
* стал :)
*/
entries=jarFile.entries();
while(entries.hasMoreElements()){
vect.add(entries.nextElement());
vc++;
}

Замечу сразу, что я писал программу для Java 1.5. Для Java 1.4 и более ранних версий работа с объектами Enumeration и Vector была бы немного другой, немного более трудной. Спасибо Sun Microsystems за облегчение и без того тяжкой участи программистов! :) Ну а теперь, имея список содержимого jar-архива, мы спокойно можем распаковывать его, не забывая создавать подкаталоги, содержащиеся в архиве. Для этого используем метод mkdir() класса File. Назовём наш метод extract(). Он может иметь следующий вид:

public void extract() {
File tmpfile;
/*
* создаём временный объект, который будет создавать каталоги
*/
JarEntry tmpentry; /* создаём временную ссылку на файл в архиве */
FileOutputStream out; /* это и так понятно */
InputStream in; /* и это тоже */
int t; /* переменная для копирования файла */
try {
/*
* создаём цикл для извлечения файлов из архива. Вот нам и пригодилась
* переменная vc
*/
for (int i = 0; i < vc; i++){
/*
* берём из вектора имя очередного файла или каталога
*/
tmpentry = vect.get(i);
tmpfile =
new File(tmpentry.getName());
/* если tmpfile – каталог, */
if (tmpentry.isDirectory()) {
/* то создаём его */
if (!tmpfile.mkdir()){
System.out.println("Can't create directory: "
+ tmpfile.getName());
/*
* если он не создаётся,
*/
return; /* выходим из функции */
}
}
/*
* ну а если tmpfile – не каталог, а файл, то спокойно извлекаем его
*/
else{
in = jarFile.getInputStream(tmpentry);
out =
new FileOutputStream(tmpfile);
while ((t = in.read()) != -1)
out.write(t);
/*
* лучше потоки ввода и вывода закрывать, иначе наша программа
*/
out.close();
/*
* может не сосем корректно работать (некоторые файлы могут
* теряться)
*/
in.close();
}
}
}
/* обрабатываем исключение */
catch (IOException e){
System.out.println(e.getMessage());
e.printStackTrace
(); /* это, по-моему, не совсем обязательно */
System.exit(0);
}
}

Ура товарищи, мы это сделали! Аналогичным образом можно работать и с zip-архивами. Необходимо только поменять JarFile и JarEntry на ZipFile и ZipEntry соответственно. На основе этого можно сделать что-нибудь более сложное и подходящее под какие-то конкретные цели. Алгоритм может быть и более оптимально построен. В статье он не совсем оптимален для пущей наглядности.

Теги: jarzip

Еще от автора

Применение WeakHashmap для списков слушателей

В статье от 11мая 1999 года Reference Objects были описаны основные идеи применения ссылочных объектов, но не приводилось детального описания. Данная статья позволит вам получить больше сведений, касающихся данной темы. В основном ссылочные объекты применяются для косвенных ссылок на память необходимую объектам. Ссылочные объекты хранятся в очереди (класс ReferenceQueue), в которой отслеживается доступность ссылочных объектов. Исходя из типа ссылочного объекта, сборщик мусора может освобождать память даже тогда, когда обычные ссылки не могут быть освобождены.

Заставки в Mustang

Согласно определению, данному в Wikipedia, заставка - это компьютерный термин, обозначающий рисунок, появляющийся во время загрузки программы или операционной системы. Заставка для пользователя является визуальным отображением инициализации программы. До выхода версии Java SE 6 (кодовое название Mustang) единственной возможностью применения заставки было создание окна, во время запуска метода main, и размещение в нем картинки. Хотя данный способ и работал, но он требовал полной инициализации исполняемой Java среды до появления окна заставки. При инициализации загружались библиотеки AWT и Swing, таким образом, появление заставки задерживалось. В Mustang появился новый аргумент командной строки, значительно облегчающий использование заставок. Этот способ позволяет выводить заставку значительно быстрее до запуска исполняемой Java среды. Окончательное добавление данной функциональности находится на рассмотрении в JCP.

Совмещение изображений

1 Введение 2 Правила визуализации и пример 3 Совмещение изображений в оперативной памяти 4 Постепенное исчезновение изображения 5 Ссылки и дополнительная информация

Еще по теме

Применение WeakHashmap для списков слушателей

В статье от 11мая 1999 года Reference Objects были описаны основные идеи применения ссылочных объектов, но не приводилось детального описания. Данная статья позволит вам получить больше сведений, касающихся данной темы. В основном ссылочные объекты применяются для косвенных ссылок на память необходимую объектам. Ссылочные объекты хранятся в очереди (класс ReferenceQueue), в которой отслеживается доступность ссылочных объектов. Исходя из типа ссылочного объекта, сборщик мусора может освобождать память даже тогда, когда обычные ссылки не могут быть освобождены.

Заставки в Mustang

Согласно определению, данному в Wikipedia, заставка - это компьютерный термин, обозначающий рисунок, появляющийся во время загрузки программы или операционной системы. Заставка для пользователя является визуальным отображением инициализации программы. До выхода версии Java SE 6 (кодовое название Mustang) единственной возможностью применения заставки было создание окна, во время запуска метода main, и размещение в нем картинки. Хотя данный способ и работал, но он требовал полной инициализации исполняемой Java среды до появления окна заставки. При инициализации загружались библиотеки AWT и Swing, таким образом, появление заставки задерживалось. В Mustang появился новый аргумент командной строки, значительно облегчающий использование заставок. Этот способ позволяет выводить заставку значительно быстрее до запуска исполняемой Java среды. Окончательное добавление данной функциональности находится на рассмотрении в JCP.

Использование потоков

1 Введение 2 Работа с выражениями типа Boolean 3 Класс JoptionPane 4 Приложение-счетчик 5 Ссылки

Перехват необрабатываемых исключений

В статье от 16 марта 2004 года Best Practices in Exception Handling были описаны приемы обработки исключений. В данной статье вы изучите новый способ обработки исключений при помощи класса UncaughtExceptionHandler добавленного в J2SE 5.0.

Использование класса LinkedHashMap

1 Введение 2 Сортировка хэш-таблицы 3 Копирование таблицы 4 Сохранение порядка доступа к элементам 5 Ссылки

Сказ про кодировки и java

С кодировками в java плохо. Т.е., наоборот, все идеально хорошо: внутреннее представление строк – Utf16-BE (и поддержка Unicode была с самых первых дней). Все возможные функции умеют преобразовывать строку из маленького регистра в большой, проверять является ли данный символ буквой или цифрой, выполнять поиск в строке (в том числе с регулярными выражениями) и прочее и прочее. Для этих операций не нужно использовать какие-то посторонние библиотеки вроде привычных для php mbstring или iconv. Как говорится, поддержка многоязычных тестов “есть в коробке”. Так откуда берутся проблемы? Проблемы возникают, как только строки текста пытаются “выбраться” из jvm (операции вывода текста различным потребителям) или наоборот пытаются в эту самую jvm “залезть” (операция чтения данных от некоторого поставщика).