Брюс Эккель - Философия Java3
print("3anncb файла " + arg). BufferedReader in =
new BufferedReader(new FileReader(arg)); zos putNextEntry(new ZipEntry(arg)). int c.
while((c = in readO) != -1)
out write(c); in closeO. out flushO.
}
out closeO.
// Контрольная сумма становится действительной
// только после закрытия файла с архивом!
pri nt ("Checksum " + csum getChecksum() getValueO);
// Теперь извлекаем файлы-
ргШСЧтение файла").
Fi 1 elnputStream fi = new FilelnputStreamCtest zip"). CheckedlnputStream csumi =
new CheckedInputStream(fi. new Adler320); ZipInputStream in2 = new ZipInputStream(csumi). BufferedlnputStream bis = new BufferedInputStream(in2). ZipEntry ze.
while((ze = in2 getNextEntry()) != null) { printCReading file " + ze). int x;
while((x = bis readO) != -1) System out write(x).
}
if(args.length == 1)
print("Контрольная сумма " + csumi getChecksum() getValueO), bis closeO.
// Альтернативный способ открытия и чтения
// файлов в формате ZIP•
ZipFile zf = new ZipFi1e("test zip").
Enumeration e = zf entriesO;
while(e hasMoreElementsO) {
ZipEntry ze2 = (ZipEntry)e nextElement().
printCFile. " + ze2). продолжение &
// ... затем данные извлекаются так же. как прежде
}
/* if(args length == 1) */
}
} ///:-
Для каждого файла, добавляемого в архив, необходимо вызвать метод put-NextEntry() с соответствующим объектом ZipEntry. Класс ZipEntry содержит все необходимое для добавления к отдельной записи Z IP-файла дополнительной информации: имени файла, размера в сжатом и обычном виде, контрольной суммы CRC, дополнительных данных, комментариев, метода сжатия, признака каталога. В исходном формате ZIP также можно задать пароли, но библиотека Java не поддерживает эту возможность. Аналогичное ограничение встречается и при использовании контрольных сумм: потоки CheckedlnputStream и Checked-OutputStream поддерживают оба вида контрольных сумм — и Adler32, и CRC32, однако в классе ZipEntry поддерживается только CRC. Это ограничение вынужденное, поскольку продиктовано требованиями формата ZIP, однако при этом быстрая контрольная сумма Adler32 оказывается в неравных условиях с CRC.
Для извлечения файлов в классе ZipInputStream предусмотрен метод getNext-Entry(), который возвращает очередной элемент архива ZipEntry. Для получения более компактной записи можно использовать для архива объект Zip File, чей метод entries() возвращает итератор Enumeration, с помощью которого можно перемещаться по доступным элементам архивного файла.
Чтобы Иметь доступ к контрольной сумме, необходимо каким-либо образом хранить представляющий ее объект Checksum. В нашем случае сохраняются ссылки на потоки CheckedlnputStream и CheckedOutputStream, хотя можно было бы просто сохранить ссылки на объекты Checksum.
Неясно, зачем в библиотеку сжатия ZIP был добавлен метод setComment(), вставляющий в архивный файл комментарий. Как указано в примере, добавить комментарий при получении архивного файла можно, но восстановить его при чтении архива потоком ZipInputStream нельзя. Полноценные комментарии поддерживаются только для отдельных вхождений ZIP-архива, объектов ZipEntry.
Конечно, уплотняемые данные не ограничены файлами; пользуясь библиотеками ZIP и GZIP, вы можете сжимать все, что угодно, даже данные сетевых потоков.
Архивы Java ARchives (файлы JAR)
Формат ZIP также применяется в файлах JAR (архивы Java ARchive), предназначенных для упаковки группы файлов в один сжатый файл. Как и все в языке Java, файлы JAR являются кросс-платформенными, поэтому не нужно заботиться о совместимости платформ. Наравне с файлами классов, в них могут содержаться также любые файлы — например, графические и мультимедийные.
Файлы JAR особенно полезны при работе с Интернетом. До их появления веб-браузерам приходилось выдавать отдельный запрос к серверу для каждого файла, необходимого для запуска апплета. Вдобавок все эти файлы не сжимались. Объединение всех нужных для запуска апплета файлов в одном сжатом файле сокращает время запроса к серверу, при этом уменьшается и загрузка сервера. Кроме того, каждый элемент архива JAR можно снабдить цифровой подписью.
Файл JAR представляет собой файл, в котором хранится набор сжатых файлов вместе с манифестом (manifest), который их описывает. (Вы можете создать манифест самостоятельно или же поручить эту работу программе jar.) За подробной информацией о манифестах JAR обращайтесь к документации JDK.
Инструмент jar, который поставляется вместе с пакетом разработки программ JDK, автоматически сжимает файлы по вашему выбору. Запускается эта программа из командной строки:
jar [параметры] место_назначения [манифест] список_файлов
Параметры запуска — просто набор букв (дефисы или другие служебные символы не нужны). Пользователи систем UNIX/Linux сразу заметят сходство с программой tar. Допустимы следующие параметры:
с Создание нового или пустого архива
t Вывод содержимого архива
х Извлечение всех файлов
х файл Извлечение файла с заданным именем
f Признак имени файла. Если не использовать этот параметр, jar решит, что входные
данные поступают из стандартного ввода, или при создании файла выходные данные будут направляться в стандартный поток вывода m Означает, что первый аргумент содержит имя файла, содержащего манифест
v Выводит краткое описание действий, выполняемых программой jar
о Сохранение файлов без сжатия (для создания файлов JAR, которые можно указать
в переменной окружения CLASSPATH) М_Отказ от автоматического создания манифеста_
Если в списке файлов имеется каталог, то его содержимое вместе с подкаталогами и всеми файлами автоматически помещается в файл JAR. Информация о пути файлов также сохраняется.
Несколько примеров наиболее распространенных вариантов запуска программы jar:
jar cf myJarFile jar * class
Команда создает файл JAR с именем myJarFile.jar, в котором содержатся все файлы классов из текущего каталога, с автоматически созданным манифестом:
jar cmf myJarFile jar myManifestFile mf * class
Почти идентична предыдущей команде, за одним исключением — в полученный файл JAR включается пользовательский манифест из файла myManifest-File.mf:
jar tf myJarFile jar
Вывод содержимого (списка файлов) архива myJarFile.jar:
jar tvf myJarFile jar
К предыдущей команде добавлен параметр v для получения более подробной информации о файлах, содержащихся в архиве myJarFile.jar:
jar cvf myApp jar audio classes image
Предполагается, что audio, classes и image — это каталоги, содержимое которых включается в файл myApp.jar. Благодаря параметру v в процессе сжатия выводится дополнительная информация об упаковываемых файлах.
Инструмент jar не обладает возможностями архиватора zip. Например, он не позволяет добавлять или обновлять файлы в уже существующем архиве JAR. Также нельзя перемещать файлы и удалять их после перемещения. Но при этом созданный файл JAR всегда читается инструментом jar на другой платформе (архиваторы zip о такой совместимости могут только мечтать).
Сериализация объектов
Сериализация (serialization) объектов Java позволяет вам взять любой объект, реализующий интерфейс Serializable, и превратить его в последовательность байтов, из которой затем можно полностью восстановить исходный объект. Сказанное справедливо и для сетевых соединений, а это значит, что механизм сериализации автоматически компенсирует различия между операционными системами. То есть можно создать объект на машине с ОС Windows, превратить его в последовательность байтов, а затем послать их по сети на машину с ОС UNIX, где объект будет корректно воссоздан. Вам не надо думать о различных форматах данных, порядке следования байтов или других деталях.
Сама по себе сериализация объектов интересна потому, что с ее помощью можно осуществить легковесное долговременное хранение (lightweight persistence). Вспомните: это означает, что время жизни объекта определяется не только временем выполнения программы — объект существует и между запусками программы. Можно взять объект и записать его на диск, а после, при другом запуске программы, восстановить его в первоначальном виде и таким образом получить эффект «живучести». Причина использования добавки «легковесное» такова: объект нельзя определить как «постоянный» при помощи некоторого ключевого слова, то есть долговременное хранение напрямую не поддерживается языком (хотя вероятно, такая возможность появится в будущем). Система выполнения не заботится о деталях сериализации — вам приходится собственноручно сериализовывать и восстанавливать объекты вашей программы. Если вам необходим более серьезный механизм сериализации, попробуйте библиотеку Java JDO или инструмент, подобный Hibernate (http://hibernate.sourceforge. net).
Механизм сериализации объектов был добавлен в язык для поддержки двух расширенных возможностей. Удаленный вызов методов Java (RMI) позволяет работать с объектами, находящимися на других компьютерах, точно так же, как и с теми, что существуют на вашей машине. При посылке сообщений удаленным объектам необходимо транспортировать аргументы и возвращаемые значения, а для этого используется сериализация объектов.
Сериализация объектов также необходима визуальным компонентам Java-Bean. Информация о состоянии визуальных компонентов обычно изменяется во время разработки. Эту информацию о состоянии необходимо сохранить, а затем, при запуске программы, восстановить; данную задачу решает сериализация объектов.