Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых
[Назад]

Библиотека примеров приложений Java

Оглавление
Выбор файлов
Простейший редактор текста
Копирование файлов UNICODE
Сохранение объекта Java в файле
Произвольные классы и файлы
Буферизация потоков
Разбор конфигура-
ционного файла

Работа с консолью
Работа с классом PrintWriter
Разбор строк класса String
Загрузка и просмотр изображений
Потоки в оперативной памяти
Конвейерные потоки
Комбинирование двух потоков
Комбинирование нескольких потоков
Поиск слова в текстовом файле
Произвольный доступ к файлу
Информация о файле
Работа с каталогами
Просмотр содержимого каталога
Просмотр каталога с фильтром
Панель для выбора каталога
Список системных свойств
Сохранение списка системных свойств
Контрольная сумма файла
Копирование, переименование, удаление файлов
Архивы ZIP
Создание архива ZIP
Распаковка архива ZIP
Обход дерева каталогов

Назад Вперед

7.28. Создание архива формата ZIP

Показан способ создания архива ZIP из файлов, расположенном в заданном каталоге, с применением классов ZipFile и ZipEntry.

Исходный текст примера

Архив проекта для Java WorkShop 2.0

Немного теории

В предыдущем разделе нашей библиотеки примеров мы кратко рассказали о классах ZipFile и ZipEntry, предназначенных для работы с архивами формата ZIP и рассмотрели методику извлечения отдельных файлов из такого архива. Здесь мы продемонстрируем способ создания архивов ZIP.

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

zos = new ZipOutputStream(
  new FileOutputStream(tempfile));

Этот объект является выходным потоком и может быть создан на базе потока FileOutputStream.

Далее при помощи метода setLevel класса ZipOutputStream нужно установить уровень сжатия:

zos.setLevel(
  Deflater.DEFAULT_COMPRESSION);

В качестве параметра методу setLevel передается целое число в диапазоне от 0 до 9 или константа Deflater.DEFAULT_COMPRESSION. В последнем случае используется уровень компрессии, принятый по умолчанию.

В классе Deflater определены и другие константы, определяющие степень сжатия:

Константа Описание
NO_COMPRESSION Сжатие не выполняется
BEST_SPEED Уровень сжатия для максимальной скорости компрессии
BEST_COMPRESSION Уровень для максимальной степени компрессии

Следующий этап создания архива ZIP заключается в формировании объектов класса ZipEntry, соответствующих элементам оглавления архива. Каждый такой элемент необходимо записать в архив методом putNextEntry:

ZipEntry ze;
ze = new ZipEntry(szName);
zos.putNextEntry(ze);

Когда элемент оглавления для добавляемого файла записан в архив, следует выполнить копирование потока, связанного с добавляемым файлом в поток класса ZipOutputStream.

Указанная операция выполняется в цикле для всех добавляемых файлов.

Описание примера

Сразу после запуска наше приложение запрашивает с консоли путь к каталогу, расположенному на локальном диске компьютера. Когда пользователь введет этот путь, наша программа создает в рабочем каталоге архивный файл формата ZIP с именем !temp.zip и добавляет в него все файлы, расположенные в рабочем каталоге.

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

Enter full path: 
c:\temp
c:\temp\ZipFileDialog.class 7722 (3875) 50%
c:\temp\FrameWindow.class 3421 (1607) 54%
c:\temp\test.zip 654 (249) 62%
c:\temp\descr.htm 22124 (5986) 73%
c:\temp\ZipFileView.class 585 (382) 35%
c:\temp\ZipFileView.java 9053 (2204) 76%
c:\temp\ZipFileView.java.bak 167 (109) 35%
c:\temp\ZipFileView.map 124 (76) 39%
c:\temp\ZipFileView.prj 169 (111) 35%
c:\temp\ZipFileView.zip 8947 (8623) 4%

После обработки всех файлов, расположенных в указанном каталоге, программа завершает свою работу.

Рассмотрим исходный текст нашей программы.

Метод main

Как мы уже говорили, путь к исходному каталогу наша программа запрашивает с консоли. Для этого мы используем метод getKbdString, определенный в нашем приложении:

String s;
System.out.println(
  "Enter full path: ");
s = new String(getKbdString());

Строка полного пути к каталогу, возвращенная этим методом, сохраняется в переменной с именем s.

Прежде чем продолжить свою работу, метод main проверяет, что указанный путь относится к существующему каталогу:

File f = new File(s);
if(!f.exists())
{
  System.out.println("\nNot found: " + s);
  System.exit(0);
}
      
if(!f.isDirectory())
{
  System.out.println(
    "\nNot directory: " + s);
  System.exit(0);
}

В противном случае работа программы завершается с сообщением об ошибке.

Если путь к каталогу указан правильно, метод main создает выходной поток для нового архивного файла с именем !temp.zip:

ZipOutputStream zos = 
  createZipOutputStream("!temp.zip");

Для этого вызывается метод createZipOutputStream, определенный в нашем приложении. Данный метод возвращает ссылку на поток класса ZipOutputStream.

Кроме того, метод main создает массив строк с именами файлов и каталогов, расположенных в указанном пользователем каталоге:

String[] sDirList = f.list();

Добавление файлов к архиву ZIP выполняется в цикле методом addFileToZip, определенным в нашем приложении:

int i;
try
{    
  for(i = 0; i < sDirList.length; i++)
  {
    File f1 = new File(
      s + File.separator + sDirList[i]);
        
    if(f1.isFile())
    {
      addFileToZip(zos, s + File.separator,
        sDirList[i]);
    }
  }  
  zos.close();
}     
catch(Exception ex)
{
  System.out.println(ex.toString());
}

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

После завершения цикла добавления файлов метод main закрывает выходной поток класса ZipOutputStream. На этом работа программы завершается.

Метод createZipOutputStream

Метод createZipOutputStream предназначен для создания выходного потока класса ZipOutputStream, привязанного к файлу. В качестве единственного параметра этому методу передается путь к создаваемому файлу архива ZIP:

static ZipOutputStream 
    createZipOutputStream(String szPath)
{
  . . .
}

Все операции выполняются методом внутри блока try-catch, так как они могут вызвать появление исключений.

Вначале метод createZipOutputStream создает для файла, путь к которому был передан через параметр, объект класса File:

File tempfile;  
ZipOutputStream zos = null;
    
try
{    
  tempfile = new File(szPath);
  . . .
}   
catch(Exception ex)
{
  System.out.println(ex.toString());
}

Далее с помощью соответствующего конструктора создается поток класса ZipOutputStream:

zos = new ZipOutputStream(
  new FileOutputStream(tempfile));

Для этого потока мы устанавливаем уровень сжатия, принятый по умолчанию:

zos.setLevel(
  Deflater.DEFAULT_COMPRESSION);

Затем метод createZipOutputStream возвращает ссылку на созданный выходной поток:

return zos;

Метод addFileToZip

Прототип метода addFileToZip представлен ниже:

static void addFileToZip(ZipOutputStream zos,
  String szPath, String szName) 
  throws Exception
{
  . . .
}

Как мы уже говорили, через первый параметр методу addFileToZip передается ссылка на выходной поток класса ZipOutputStream, через второй - путь к каталогу с файлами, а через третий - имя добавляемого файла. С помощью ключевого слова throws мы указали, что в процессе работы этого метода могут возникать исключения, которые необходимо обработать в вызывающем методе.

Свою работу метод addFileToZip начинает с того, что выводит на консоль путь к файлу, которы добавляется в архив:

System.out.print(szPath + szName);

Далее для добавляемого файла мы создаем новый элемент оглавления (как объект класса ZipEntry) и записываем его в выходной поток zos класса ZipOutputStream методом putNextEntry:

ZipEntry ze;
ze = new ZipEntry(szName);
zos.putNextEntry(ze);

Теперь нужно скопировать в выходной поток zos сам добавляемый файл. Эта операция выполняется в цикле:

FileInputStream fis = 
  new FileInputStream(szPath + szName);
  
byte[] buf = new byte[8000];
int nLength;
while(true)
{
  nLength = fis.read(buf);
  if(nLength < 0)
    break;
  zos.write(buf, 0, nLength);
}

После завершения цикла необходимо закрыть поток, связанный с добавляемым файлом и новый элемент оглавления:

fis.close();
zos.closeEntry();

Теперь элемент оглавления полностью сформирован и записан в выходной поток zos, связанный с архивом. Мы извлекаем из этого элемента сведения об исходном размере файла и размере файла после сжатия, а затем отображаем эту информацию на консоли:

long nSize = ze.getSize();
long nCompressedSize = 
  ze.getCompressedSize();
    
long nPercent = 100 - 
   ((nCompressedSize * 100) / nSize);
    
System.out.println(" " + nSize + " (" +
  nCompressedSize + ") " + nPercent + "%");

Далее метод addFileToZip возвращает управление вызвавшему его методу.


Назад Вперед

[Назад]