Elettracompany.com

Компьютерный справочник
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Java util zip

Учимся программировать на Java с нуля

ZIP-архивы в языке Java

ZIP-архивы позволяют хранить один и более файлов в (обычно) сжатом формате. У каждого ZIP-архива имеется заголовок, содеражащий информацию вроде имени файла или использовавшегося для него метода сжатия. В Java для чтения ZIP-архивов применяется класс ZipInputStream. В каждом таком архиве всегда требуется просматривать отдельные записи(entries).

Метод getNextEntry возвращает описывающий запись объект типа ZipEntry. Метод read класс ZipInputStream изменяется так, чтобы он возвращал -1 в конце текущий записи(а не просто в конце ZIP-файла).

Далее вызывается метод closeEntry для получения возможности перехода к считыванию следующей записи. Ниже приведена типичная кодовая последовательность для выполнения считывания содержимого ZIP-файла:

Для считывания содержимого конкретной записи из ZIP-файла эффективнее использовать не стандартный метод read, а методы какого-то обладающего большими находящегося внутри ZIP-архива, можно применить следующий цикл:

В случае возникновения ошибки при считывании ZIP-файла класс ZipInputStream выдает исключение ZipException. Обычно подобное происходит при повреждении ZIP-файла.

Для записи ZIP-файла применяется класс ZipOutputStream. Для каждой записи, которую требуется поместить в ZIP-файл, создается объект ZipEntry. Желаемое имя для файла передается конструктору ZipEntry, тот устанавливает остальные параметры, вроде даты создания файла и метода распаковки.

При желании эти параметры могут переопределяться. Далее вызывается метод putNextEntry класса ZipOutputStream для начала процесса записи нового файла. После этого данные самого файла отправляются потоку ZIP. По завершении вызывается метод closeEntry. Затем все эти действия выполняются повторно для всех остальных файлов, которые требуется сохранить в ZIP-архиве. Ниже приведена общая схема необходимого кода:

JAR-файлы представляют собой те же ZIP-файлы, но только содержат записи несколько иного вида, называемые манифестом. Для считывания и записи манифестов применяются классы JarInputStream и JarOutputStream.

ZIP-потоки являются прекрасным примером мощи потоковой абстракции. При считывании данных, которые хранятся в сжатом виде, не нужно волноваться о том, будут ли они распаковаться по мере запрашивания. И источником байтов в ZIP-форматах вовсе не обязательно должен быть именно файл: ZIP-данные могут поступать и через сетевое подключение. На самом деле, при всяком считывании JAR-файла загрузчик классов аплета будет считывать и распаковывать данные именно из сети.

Рис.2. Программа ZipTest

Программа код которой приведен ниже, позволяет открывать ZIP-архив, после чего отображает все хранящиеся внутри него файлы в комбинированном списке в нижней части экрана. В случае выбора какого-то одного из этих файлов она отображает его содержимое в текстовой области, как показано на рис.2.

Java Zip and Unzip Files and Folders

Here we will learn about how to zip and unzip files and folders in java.

If information contains redundant data it will be tough to store and transfer the data. So we will go for compression which will give efficient representation of the data. For zipping many algorithms are there.

Java provides the java.util.zip package for zipping and unzipping the files. The class ZipOutputStream will be useful for compressing. It is an output stream filter which will write files to any File output stream in zip format. The class ZipInputStream will be useful for decompressing. It is an input stream which will read files that are in zip format.

How to Zip Files in Java?

For zipping purpose we have many algorithms. If we are not mentioning any alogorithm through any method it will use default compression method that is DEFLATED compression. Deflated compression is almost near to Huffman coding.

Now we will see one example.

Problem: We want to zip the directory which has multiple files along with sub folders.

Solution: Zipping a file is very easy. But when we are zipping a folder which contains sub folders we should take care about the relative paths of files which have to be zipped.

For example take directory named as first which is located in E disk. It contains one subfolder along with multiple files. We have to zip it now.

Procedure :

Step 1: We should list out all files in the directory. listFiles() method will return total files (directories + files) in that directory. We can use this method to list out the total files. For this we have to check whether it is a directory or not. If it is a directory then again list out the files in that subdirectory. Continue this process until all files are listed out. This is recursive process.

Step 2: After listing out the files, we should create a file output stream for output zip folder. So that it will create output zip folder and write the contents to it.

Читать еще:  Java jdk 9

Step 3: We should create a zip output stream which will write file contents to the file output stream in the format of zip.

Step 4: Now we have to zip each file in list according to their paths.

  • Create an input stream for a file. So that it can read file contents.
  • Create a zip Entry object for file with relative path only because if use absolute path it can’t find files so zipping is not possible. So that we can add this file to zip out stream. For adding putNextEntry() method of ZipOutputStream will be useful.
  • Now zip output stream will write these file contents in the format of zip to the file output stream.
  • Close zip entry and close file input stream

This is the process of zipping one file. So do the same for every file in the list.

Step 5: As zipping of all files is done. Now close all IO streams. Proper closing of IO streams will prevent the corruption of zip files.

Zip-архивирование в Java

Считывание содержимого Zip-архива.

В Java для чтения Zip-архивов применяется класс ZipInputStream. В каждом таком архиве всегда требуется просматривать отдельные записи (entries). Метод getNextEntry возвращает описывающий запись объект типа ZipEntry. Метод read класса ZipInputStream изменяется так, чтобы он возвращал -1 в конце текущей записи (а не просто в конце Zip-файла). Далее вызывается метод closeEntry для получения возможности перехода к считыванию следующей записи.

ZipInputStream zin = new ZipInputStream(new FileInputStream(zipName));
ZipEntry entry;
while ((entry = zin.getNextEntry()) != null) <
//анализ entry
//считывание содежимого
zin.closeEntry();
>
zin.close();

Для считывания содержимого конкретной записи из Zip-файла эффективнее использовать не стандартный метод read, а методы какого-то обладающего большими возможностями потокового фильтра. Например, для считывания текстового файла, находящегося внутри Zip-архива, можно применить следующий цикл:

Scanner in = new Scanner(zin);
while (in.hasNextLine()) <
//выполнение операций с in.nextLine()

Запись в Zip-архив.

Для записи Zip-файла применяется класс ZipOutputStream. Для каждой записи, которую требуется поместить в Zip-файл, создается объект ZipEntry. Желаемое имя для файла передается конструктору ZipEntry; тот устанавливает устанавливает остальные параметры, вроде даты создания файла и метода распаковки. При желании эти параметры могут переопределяться. Далее вызывается метод putNextEntry класса ZipOutputStream для начала процесса записи нового файла. После этого данные самого файла отправляются потоку ZIp. По завершении вызывается метод closeEntry. Затем все эти действия выполняются повторно для всех остальных файлов, которые требуется сохранить в Zip-архиве. Ниже приведена общая схема необходимого кода:

FileOutputStream fout = new FileOutputStream(«test.zip»);
ZipOutputStream zout = new ZipoutputStream(fout);
//Для всех файлов:
<
ZipEntry ze = new ZupEntry(«имя файла»);//Имя файла — имя файла в архиве
zout.putNextEntry(ze);
//отправка данных в поток zout
zout.closeEntry();
>
zout.close();

Сжатие объектов с сохранением

Имеется класс «Работник» реализующий интерфейс для сериализации:

public class Employee implements Serializable <

String name;
int age;
int salary;

public Employee(String name, int age, int salary) <
this.name = name;
this.age = age;
this.salary = salary;
>

public void print() <
System.out.println(«Record for: » + name);
System.out.println(«Name: » + name);
System.out.println(«Age: » + age);
System.out.println(«Salary: » + salary);
>
>

Сохранить объекты данного класса мы можем следующим кодом:

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

public class SaveEmployee <

public static void main(String argv[]) throws
Exception <
Employee sarah = new Employee(«S. Jordan», 28,
56000);
Employee sam = new Employee(«S. McDonald», 29,
58000);
FileOutputStream fos = new FileOutputStream(«db»);
GZIPOutputStream gz = new GZIPOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(gz);
oos.writeObject(sarah);
oos.writeObject(sam);
oos.flush();
oos.close();
fos.close();
>
>

Здесь всё просто, данные мы сохраняем в файл (FileOutputStream) перед этим сжав их (GZIPOutputStream), а в роли данных выступают объекты (ObjectOutputStream).

Загрузить сохраненные сжатые объекты также просто как и сохранить их:

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

public class ReadEmployee <

public static void main(String argv[]) throws
Exception <
FileInputStream fis = new FileInputStream(«db»);
GZIPInputStream gs = new GZIPInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(gs);
Employee sarah = (Employee) ois.readObject();
Employee sam = (Employee) ois.readObject();
sarah.print();
sam.print();
ois.close();
fis.close();
>
>

Данные считываются из файла (FileInputStream), файлы являются сжатыми (GZIPInputStream), данными являются объекты (ObjectInputStream).

Также можно обмениваться сжатыми объектами между сервером/клиентом (с использованием сокетов), ниже представлен код отправки сжатого объекта клиенту:

GZIPOutputStream gzipout =
new GZIPOutputStream(socket.getOutputStream());
ObjectOutputStream oos =
new ObjectOutputStream(gzipout);
oos.writeObject(obj);
gzipos.finish();

Ниже представлен код по получению и декомпрессии данных объекта от сервера:

Socket socket = new Socket(remoteServerIP, PORT);
GZIPInputStream gzipin =
new GZIPInputStream(socket.getInputStream());
ObjectInputStream ois = new ObjectInputStream(gzipin);
Object o = ois.readObject();

Если Вам понравилась статья, проголосуйте за нее

Голосов: 9 Голосовать

Добавление файлов в zip-файл с помощью Java

в настоящее время я извлекаю содержимое файла war, а затем добавляю некоторые новые файлы в структуру каталогов, а затем создаю новый файл war.

все это делается программно с Java-но мне интересно, не было бы более эффективным скопировать файл war, а затем просто добавить файлы — тогда мне не пришлось бы ждать, пока война расширится, а затем снова должна быть сжата.

Читать еще:  Exceptionininitializererror java что это

Я не могу найти способ сделать это в документации Хотя или любые онлайн-примеры.

кто-нибудь может дать некоторые подсказки или указатели?

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

кто-нибудь имеет опыт или отзывы о TrueZip или может рекомендовать другие подобные библиотеки?

12 ответов

в Java 7 мы получили Файловая Система Zip что позволяет добавлять и изменять файлы в zip (jar, war) без ручной переупаковки.

мы можем напрямую записывать в файлы внутри zip-файлов, как в следующем примере.

Как уже упоминалось, невозможно добавить контент к существующему zip (или war). Тем не менее, можно создать новый zip на лету без временной записи извлеченного содержимого на диск. Трудно догадаться, насколько быстрее это будет, но это самый быстрый, который вы можете получить (по крайней мере, насколько я знаю) со стандартной Java. Как упоминал Карлос Тасада, SevenZipJBindings может выжать из вас несколько дополнительных секунд, но перенос этого подхода на SevenZipJBindings все равно будет быстрее, чем использование временных файлов с той же библиотекой.

вот некоторый код, который записывает содержимое существующего zip (war.ZIP) и добавляет дополнительный файл (ответ.txt) на новый zip (append.промелькнуть.) Все, что требуется, это Java 5 или более поздняя версия, никаких дополнительных библиотек не требуется.

У меня было аналогичное требование когда — то назад-но это было для чтения и записи zip-архивов (.формат войны должен быть похож). Я попытался сделать это с существующими потоками Java Zip, но нашел часть записи громоздкой — особенно когда каталоги, в которых участвуют.

Я рекомендую вам попробовать TrueZIP (open source — Apache style licensed) библиотека, которая предоставляет любой архив как виртуальную файловую систему, в которой вы можете читать и писать как обычно файловая система. Он работал как шарм для меня и значительно упростило мое развитие.

вы можете использовать этот кусок кода я написал

Я не знаю библиотеки Java, которая делает то, что вы описываете. Но то, что вы описали, практично. Вы можете сделать это в .NET, используя DotNetZip.

Майкл Крауклис прав, что вы не можете просто «добавить» данные в файл войны или zip-файл, но это не потому, что в файле войны есть указание «конец файла». Это потому, что формат war (zip) включает в себя каталог, который обычно присутствует в конце файла, который содержит метаданные для различных записей в файле war. Наивное добавление к файлу war не приводит к обновлению каталога, и поэтому у вас просто есть файл war с добавленным к нему мусором.

необходим интеллектуальный класс, который понимает формат и может читать + обновлять файл war или zip-файл, включая соответствующий каталог. DotNetZip делает это без распаковки / повторного сжатия неизмененных записей, как вы описали или пожелали.

Как говорит Чизо, нет никакого способа сделать это. AFAIK передние концы zip делают то же самое, что и вы внутри.

в любом случае, если вы беспокоитесь о скорости извлечения/сжатия всего, вы можете попробовать SevenZipJBindings библиотека.

Я покрыл эту библиотеку в моем блог несколько месяцев назад (извините за авто-продвижение). Как пример, извлечение 104mb zip-файла с помощью java.утиль.zip занял у меня 12 секунд, при использовании этой библиотеки занимает 4 секунды.

в обеих ссылках вы можете найти примеры того, как его использовать.

надеюсь, что это помогает.

используя режим добавления на любом виде структурированные данные, такие как zip-файлы или tar файлы-это не то, что вы действительно можете ожидайте работы. Этот формат файла имейте внутренний » конец файла» индикация встроена в формат данных.

Если вы действительно хотите пропустить промежуточный шаг un-waring / re-waring, вы можете прочитать файл файла войны, получить все записи zip, а затем написать в новый файл войны » добавление» новые записи, которые вы хотели добавить. Не идеальное, но, по крайней мере, более автоматизированное решение.

еще одно решение: вы можете найти код ниже полезным и в других ситуациях. Я использовал ant таким образом для компиляции каталогов Java, генерации файлов jar, обновления zip-файлов.

Это простой код для получения ответа с помощью сервлета и отправки ответа

вот Java 1.7 версия Liam answer, которая использует try с ресурсами и Apache Commons IO.

вывод записывается в новый zip-файл, но его можно легко изменить для записи в исходный файл.

это работает 100% , если вы не хотите использовать дополнительные библиотеки .. 1) Во-первых, класс, который добавляет файлы в zip ..

2) Вы можете вызвать его в ваш контроллер ..

вот примеры того, как легко файлы могут быть добавлены к существующему zip с помощью TrueVFS:

Читать еще:  Случайные погрешности это ошибки

TrueVFS, преемник TrueZIP, использует функции Java 7 NIO 2 под капотом, когда это необходимо, но предлагает гораздо больше возможностей как потокобезопасное асинхронное параллельное сжатие.

остерегайтесь также, что Java 7 ZipFileSystem по умолчанию уязвимы для OutOfMemoryError на огромные вложения.

Java.util.zip.ZipException: ошибка при открытии zip файла

У меня есть файл Jar, который содержит другие вложенные Jars. Когда я вызываю новый конструктор JarFile() в этом файле, я получаю исключение, в котором говорится:

java.util.zip.ZipException: ошибка при открытии zip файла

Когда я вручную распакую содержимое этого Jar файла и снова застегиваю его, он отлично работает. Также обратите внимание, что это исключение видно только в версиях WebSphere 6.1.0.7 и более поздних версиях. То же самое отлично работает с tomcat и WebLogic. Кроме того, когда я использую JarInputStream вместо JarFile, я могу читать содержимое файла Jar без каких-либо исключений. Пожалуйста, дайте мне знать, если у вас есть идеи о том, как это можно исправить.

11 ответов

Убедитесь, что ваш файл jar не поврежден. Если он поврежден или не сможет распаковать, эта ошибка будет иметь место.

12 JohnyCash [2011-09-22 04:48:00]

Я столкнулся с той же проблемой. У меня был архив zip, который java.util.zip.ZipFile не смог обработать, но WinRar распаковал его просто отлично. Я нашел статью о SDN о параметрах сжатия и распаковки в Java. Я слегка модифицировал один из примеров кода для создания метода, который, наконец, мог обрабатывать архив. Trick использует ZipInputStream вместо ZipFile и в последовательном чтении zip-архива. Этот метод также способен обрабатывать пустой почтовый архив. Я считаю, что вы можете настроить метод в соответствии с вашими потребностями, поскольку все zip-классы имеют эквивалентные подклассы для архивов .jar.

10 VonC [2008-11-28 10:16:00]

Он может быть связан с log4j.

У вас есть файл log4j.jar в пути класса Java Java (как определено в файле запуска), а также пути к классу приложений?

Если вы убедитесь, что файл log4j.jar находится в пути класса java и что он НЕ находится в каталоге web-inf/lib вашего веб-приложения.

Он также может быть связан с ant version (может быть, это не ваш случай, но я его здесь помещаю для справки):

У вас есть .class файл в вашем пути к классу (т.е. не каталог или файл .jar). Начиная с ant 1.6, ant откроет файлы в проверке классов для записей манифеста. Это попытка открытия завершится с ошибкой «java.util.zip.ZipException»

Проблема не существует с ant 1.5, так как она не пытается открыть файлы. — поэтому убедитесь, что ваш classpath не содержит файлы .class.

С другой стороны, считали ли вы, что отдельные банки?
Вы можете в манифесте вашей главной банки, обратитесь к другим баночкам с этим атрибутом:

Затем поместите все ваши банки в одну папку.
Опять же, может быть недействительным для вашего дела, но все еще там для справки.

8 Artur. [2008-11-28 20:50:00]

Я видел это исключение раньше, чем то, что JVM считает temp, недоступно из-за отсутствия или отсутствия разрешения на запись.

3 Marius K [2011-02-08 20:34:00]

Я решил это, очистив jboss-x.y.z/server [config]/tmp и jboss-x.y.z/server/[config]/рабочие каталоги.

2 Tant4lus [2014-09-23 22:03:00]

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

Я столкнулся с этими проблемами из-за поврежденных ZIP Fils

Проверьте, был ли загружен ваш JAR файл. Полностью

1 centic [2015-04-23 22:44:00]

Я видел это с определенным Zip файлом с Java 6, но он ушел, когда я перешел на Java 8 (не тестировал Java 7), поэтому кажется, что более новые версии ZipFile в Java поддерживают больше алгоритмов сжатия и, следовательно, могут читать файлы, которые не работают с более ранними версиями.

Может быть, zip файл поврежден или брошен при загрузке.

Liquibase получала эту ошибку для меня. Я решил это после того, как я отлаживался и смотрел, как Liquibase пытается загрузить библиотеки и обнаружил, что это ошибка в файлах манифеста для commons-codec-1.6.jar. По сути, есть либо поврежденный zip файл где-то на вашем пути, либо используется несовместимая версия. Когда я исследовал репозиторий Maven для этой библиотеки, я обнаружил, что появились более новые версии и добавлена ​​новая версия в pom.xml. На этом я смог продолжить.

0 radoh [2017-03-30 15:32:00]

Я получаю исключение

при распаковке архива на Java. Сам архив не выглядел поврежденным, так как 7zip (и другие) открыли его без каких-либо проблем или жалоб на недопустимый CRC.

Я перешел на Apache Commons Compress для чтения zip-записей и решил проблему.

Ссылка на основную публикацию
Adblock
detector