Перейти к основному содержимому

Работа с ZIP-архивами

Кроме общего функционала для работы с файлами Java предоставляет функциональность для работы с таким видом файлов как zip-архивы. Для этого в пакете java.util.zip определены два класса - ZipInputStream и ZipOutputStream

ZipOutputStream. Запись архивов​

Для создания архива используется класс ZipOutputStream. Для создания объекта ZipOutputStream в его конструктор передается поток вывода:

ZipOutputStream(OutputStream out)

Для записи файлов в архив для каждого файла или каталога создается объект ZipEntry, в конструктор которого передается имя записи внутри архива. А чтобы добавить каждый объект ZipEntry в архив, применяется метод putNextEntry().

Создадим архив:

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

public class Program {
public static void main(String[] args) {
String filename = "notes.txt";
try (ZipOutputStream zout = new ZipOutputStream(new FileOutputStream("output.zip"));
FileInputStream fis = new FileInputStream(filename)) {
ZipEntry entry1 = new ZipEntry("notes.txt");
zout.putNextEntry(entry1);
// добавляем содержимое к архиву
fis.transferTo(zout);
// закрываем текущую запись для новой записи
zout.closeEntry();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}

После добавления объекта ZipEntry в поток нам также надо добавить в него и содержимое файла. Для этого можно вызвать метод transferTo() у входного потока: fis.transferTo(zout);. В конце надо закрыть текущую запись с помощью метода closeEntry(). Метод putNextEntry() автоматически закрывает текущую запись, если она еще открыта. После этого можно добавлять в архив новые файлы - в этом случае все вышеописанные действия для каждого нового файла повторяются.

Чтение архивов. ZipInputStream​

Для чтения архивов применяется класс ZipInputStream. В конструкторе он принимает поток, указывающий на zip-архив:

ZipInputStream(InputStream in)

Для считывания файлов из архива ZipInputStream использует метод getNextEntry(), который возвращает объект ZipEntry. Если записей больше нет, метод возвращает null. Объект ZipEntry представляет отдельную запись в zip-архиве — файл или каталог, а метод getName() возвращает ее имя. Например, считаем какой-нибудь архив:

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

public class Program {
public static void main(String[] args) {
try (ZipInputStream zin = new ZipInputStream(new FileInputStream("output.zip"))) {
ZipEntry entry;
String name;
while ((entry = zin.getNextEntry()) != null) {
name = entry.getName(); // получим название файла
System.out.printf("File name: %s \n", name);

// распаковка
FileOutputStream fout = new FileOutputStream("new" + name);
for (int c = zin.read(); c != -1; c = zin.read()) {
fout.write(c);
}
zin.closeEntry();
fout.close();
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}

ZipInputStream в конструкторе получает ссылку на поток ввода. И затем в цикле выводятся имена всех файлов, которые находятся в данном архиве. При чтении методом read() значение -1 означает конец текущей записи.

Затем данные извлекаются из архива и сохраняются в новые файлы, которые находятся в той же папке и которые начинаются с "new".