Главная страница

Ответы на вопросы по ревью 4. Java io. Ключевым понятием здесь является понятие потока


Скачать 1.93 Mb.
НазваниеJava io. Ключевым понятием здесь является понятие потока
Дата03.07.2022
Размер1.93 Mb.
Формат файлаdoc
Имя файлаОтветы на вопросы по ревью 4.doc
ТипДокументы
#623608
страница37 из 39
1   ...   31   32   33   34   35   36   37   38   39

Компрессия


Библиотека ввода/вывода Java содержит классы, поддерживающие чтение и запись потоков в компрессированном формате. Они являются оберткой для существующих классов ввода/вывода для обеспечения возможности компрессирования.

Эти классы не наследуются от классов Reader и Writer, а вместо этого они являются частью иерархии InputStream и OutputStream. Это происходит потому, что библиотека компрессии работает с байтами, а не с символами. Однако вы можете иногда встретить необходимость смешивания двух типов потоков. (Помните, что вы можете использовать InputStreamReader и OutputStreamWriter для обеспечения простой конвертации одного типа в другой.)

Классы компрессии

Функция

CheckedInputStream

GetCheckSum( ) производит контрольную сумму для любого InputStream (только не декомпрессию).

CheckedOutputStream

GetCheckSum( ) производит контрольную сумму для любого OutputStream (только не декомпрессию).

DeflaterOutputStream

Базовый класс для классов компрессии.

ZipOutputStream

DeflaterOutputStream, который компрессирует данные в файл формата Zip.

GZIPOutputStream

DeflaterOutputStream, который компрессирует данные в файл формата GZIP.

InflaterInputStream

Базовый класс для классов декомпрессии.

ZipInputStream

InflaterInputStream, который декомпрессирует данные, хранящиеся в файле формата Zip.

GZIPInputStream

InflaterInputStream, который декомпрессирует данные, хранящиеся в файле формата GZIP.

Хотя существует много алгоритмов компрессии, Zip и GZIP, вероятно, наиболее часто используемые. Поэтому вы можете легко манипулировать вашими компрессированными данными с помощью многих инструментов, существующих для чтения и записи этих форматов.

Простая компрессия с помощью GZIP


Интерфейс GZIP прост, и поэтому он является более подходящим, когда вы имеете единственный поток данных, которые хотите компрессировать (в отличие от случая, когда вы имеете кусочки разнородных данных). Здесь приведен пример компрессии единичного файла:

//: c11:GZIPcompress.java

// Использование GZIP компрессии для компрессирования

// файла, имя которого получается из командной строки.

import java.io.*;

import java.util.zip.*;
public class GZIPcompress {

// Исключение выбрасываются на консоль:

public static void main(String[] args)

throws IOException {

BufferedReader in =

new BufferedReader(

new FileReader(args[0]));

BufferedOutputStream out =

new BufferedOutputStream(

new GZIPOutputStream(

new FileOutputStream("test.gz")));

System.out.println("Writing file");

int c;

while((c = in.read()) != -1)

out.write(c);

in.close();

out.close();

System.out.println("Reading file");

BufferedReader in2 =

new BufferedReader(

new InputStreamReader(

new GZIPInputStream(

new FileInputStream("test.gz"))));

String s;

while((s = in2.readLine()) != null)

System.out.println(s);

}

} ///:

Использование классов компрессии достаточно понятно — вы просто оборачиваете ваш поток вывода в GZIPOutputStream или ZipOutputStream, а ваш поток ввода в GZIPInputStream или ZipInputStream. Все остальное - это обычные операции чтения и записи. Это пример смешивания символьно-ориентированных потоков и байт-ориентированных потоков: in использует класс Reader, несмотря на то, что конструктор GZIPOutputStream может принимать только объекты OutputStream, а не объекты Writer. Когда файл будет открыт, GZIPInputStream конвертируется в Reader.

Многофайловое хранение с использованием Zip


Библиотека, поддерживающая Zip формат, более обширная. С ее помощью вы можете легко хранить множественные файлы, есть даже отдельные файлы, которые делают легким процесс чтения Zip файла. Библиотека использует стандартный Zip формат, так что он может работать совместно со всеми инструментами, которые доступны в Internet. Следующий пример имеет ту же форму, что и предыдущий, но он обрабатывает столько аргументов командной строки, сколько вы захотите. Кроме того, он показывает использование классов Checksum для подсчета и проверки контрольной суммы для файла. Есть два типа Checksum : Adler32 (который быстрее) и CRC32 (который медленнее, но немного более аккуратный).

//: c11:ZipCompress.java

// Использует компрессию Zip для компрессии любого

// числа файлов, переданных из командной строки.

import java.io.*;

import java.util.*;

import java.util.zip.*;
public class ZipCompress {

// Исключение выбрасывается на консоль:

public static void main(String[] args)

throws IOException {

FileOutputStream f =

new FileOutputStream("test.zip");

CheckedOutputStream csum =

new CheckedOutputStream(

f, new Adler32());

ZipOutputStream out =

new ZipOutputStream(

new BufferedOutputStream(csum));

out.setComment("A test of Java Zipping");

// Хотя нет соответствующего getComment().

for(int i = 0; i < args.length; i++) {

System.out.println(

"Writing file " + args[i]);

BufferedReader in =

new BufferedReader(

new FileReader(args[i]));

out.putNextEntry(new ZipEntry(args[i]));

int c;

while((c = in.read()) != -1)

out.write(c);

in.close();

}

out.close();

// Контрольная сумма действительна только после

// того, как файл будет закрыт!

System.out.println("Checksum: " +

csum.getChecksum().getValue());

// Теперь вытянем файлы:

System.out.println("Reading file");

FileInputStream fi =

new FileInputStream("test.zip");

CheckedInputStream csumi =

new CheckedInputStream(

fi, new Adler32());

ZipInputStream in2 =

new ZipInputStream(

new BufferedInputStream(csumi));

ZipEntry ze;

while((ze = in2.getNextEntry()) != null) {

System.out.println("Reading file " + ze);

int x;

while((x = in2.read()) != -1)

System.out.write(x);

}

System.out.println("Checksum: " +

csumi.getChecksum().getValue());

in2.close();

// Альтернативный способ для открытия и чтения

// zip файлов:

ZipFile zf = new ZipFile("test.zip");

Enumeration e = zf.entries();

while(e.hasMoreElements()) {

ZipEntry ze2 = (ZipEntry)e.nextElement();

System.out.println("File: " + ze2);

// ... и вытягиваем данные, как и раньше

}

}

} ///:

Для каждого файла, добавляемого в архив, вы должны вызвать putNextEntry( ) и передать ему объект ZipEntry. Объект ZipEntry содержит обширный интерфейс, который позволит вам получить и установить все данные, доступные для этого конкретного включения в ваш Zip файл: имя, компрессированный и не компрессированный размеры, дата, CRC контрольная сумма, дополнительное поле данных, комментарий, метод компрессии и есть ли включаемые директории. Однако, хотя формат Zip имеет возможность установки пароля, это не поддерживается в Zip библиотеке Java. И хотя CheckedInputStream и CheckedOutputStream поддерживают обе контрольные суммы Adler32 и CRC32, класс ZipEntry поддерживает только интерфейс для CRC. Это является ограничением лежащего в основе Zip формата, и это может ограничить вас в использовании быстрого Adler32.

Для извлечения файлов ZipInputStream имеет метод getNextEntry( ), который возвращает следующий ZipEntry, если он существует. В качестве более краткой альтернативы, вы можете читать файл, используя объект ZipFile, который имеет метод entries( ), возвращающий Enumeration из ZipEntries.

Для чтения контрольной суммы вы должны как-то получить доступ к ассоциированному объекту Checksum. Здесь получается ссылка на объекты CheckedOutputStream и CheckedInputStream, но вы также могли просто владеть ссылкой на объект Checksum.

Трудным методом для потоков Zip является setComment( ). Как показано выше, вы можете установить комментарий, когда вы записываете файл, но нет способа получить коментарий в ZipInputStream. Комментарии появились для полной поддержки базиса включение-за-включением только через ZipEntry.

Конечно, вы не ограничены в файлах, когда используете библиотеки GZIP или Zip — вы можете компрессировать все, что угодно, включая данные для посылки через сетевое соединение.

Java архивы (JAR'ы)


Формат Zip также используется в файле, формата JAR (Java ARchive), который является способом сбора группы файлов в один компрессированный файл, так же как и Zip. Однако, как и все остальное в Java, JAR файлы являются кроссплатформенными, так что вам не нужно беспокоится о возможностях платформы. Вы также можете включить звуковой и графический файл наряду с файлами классов.

JAR файлы обычно полезны, когда вы имеете дело с Internet. До появления JAR файлов ваш Web броузер делал повторяющиеся запросы к Web серверу для загрузки всех файлов, из которых состоит апплет. Кроме того, каждый из этих файлов был не компрессирован. При сборе всех этих файлов для определенного апплета в единый JAR файл необходим только один запрос к серверу, а передача пройдет быстрее из-за компрессии. А каждое включение в JAR файл может иметь цифровую подпись для безопасности (обратитесь за деталями к документации по Java).

JAR файл состоит из единого файла, содержащего набор файлов, упакованных с помощью Zip, наряду с “манифестом”, который описывает их. (Вы можете создать свой собственный файл манифеста; в противном случае программа jar сделает это за вас.) Вы можете найти больше информации о файлах манифеста JAR в HTML документации для JDK.

Утилита jar, пришедшая вместе с JDK от Sun, автоматически компрессирует файлы по вашему выбору. Вы можете вызвать ее из командной строки:

jar [options] destination [manifest] inputfile(s)

Опции - это просто набор символов (не нужно ни дефисов, ни другой индикации). Пользователи Unix/Linux заметят сходство с опциями tar. Вот они:

c

Создает новый или пустой архив.

t

Список содержания.

x

Извлечь все файлы.

x file

Извлекает указанный файл.

f

Говорит: “Я дам тебе имя файла”. Если вы не используете это, jar поймет, что ввод должен идти через стандартный ввод или, если создается файл, вывод происходит через стандартный вывод.

m

Говорит о том, что первый аргумент будет именем файла манифеста, созданного пользователем.

v

Генерирует подробный вывод, описывающий то, что делает jar.

0

Только хранение файлов; не компрессирует файлы (используйте для создания JAR файла, который вы можете поместить в ваш classpath).

M

Не выполняется автоматическое создание файла манифеста.

Если поддиректории включаются в файлы, помещаемые в JAR файл, эти поддиректории добавляются автоматически, включая все вложенные поддиректории и т.д. Информация о пути тоже сохраняется.

Вот типичный способ вызова jar:

jar cf myJarFile.jar *.class

Это создает JAR файл, называемый myJarFile.jar, содержащий все файлы классов из текущей директории наряду с автоматически сгенерированным файлом манифеста.

jar cmf myJarFile.jar myManifestFile.mf *.class

Как и в предыдущем примере, но добавляется файл манифеста, созданный пользователем. Он называется myManifestFile.mf.

jar tf myJarFile.jar

Производится содержание файла myJarFile.jar.

jar tvf myJarFile.jar

Добавляет флаг “verbose”, чтобы получить более детальную информацию о файлах в myJarFile.jar.

jar cvf myApp.jar audio classes image

Принимая во внимание, что audioclasses и image являются поддиректориями, таким образом, все собирается в файл myApp.jar. Также включен флаг “verbose”, чтобы иметь обратную связь, пока работает программа jar.

Если вы создаете JAR файл, используя опцию 0, такой файл может быть помещен в ваш CLASSPATH:

CLASSPATH="lib1.jar;lib2.jar;"

После этого Java может искать файлы lib1.jar и lib2.jar.

Инструмент jar не является таким же полезным, как утилита zip. Например, вы не можете добавить или обновить файлы существующего JAR файла; вы можете создать JAR файл только с самого начала. Также вы не можете переместить файл в JAR файл и стереть его сразу, как только он будет перемещен. Однако JAR файл, созданный на одной платформе, может быть прочитан инструментом jar на любой другой платформе (проблема, которая иногда надоедает с утилитой zip).

Как вы увидите в Главе 13, JAR файлы также используются для упаковки JavaBeans.
1   ...   31   32   33   34   35   36   37   38   39


написать администратору сайта