1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-thinking-in-java-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
10.8 压缩.md 19 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 11.03.2025 09:15 d56454c

10.8 Сжатие данных

Java 1.1 также добавила классы, поддерживающие чтение и запись сжатых данных в различных форматах. Эти классы были интегрированы в существующую систему ввода-вывода, чтобы обеспечить возможность сжатия.

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

Классы сжатия Java 1.1 Функциональность
CheckedInputStream getChecksum() вычисляет контрольную сумму для любого InputStream (не только для распакованного)
CheckedOutputStream getChecksum() вычисляет контрольную сумму для любого OutputStream (не только для распакованного)
DeflaterOutputStream Базовый класс для сжатия данных
ZipOutputStream DeflaterOutputStream, который сжимает данные в формат Zip
GZIPOutputStream DeflaterOutputStream, который сжимает данные в формат GZIP
InflaterInputStream Базовый класс для распаковки данных
ZipInputStream InflaterInputStream, который распаковывает данные, сохраненные в формате Zip
GZIPInputStream InflaterInputStream, который распаковывает данные, сохраненные в формате GZIP

Интерфейс GZIP очень прост, поэтому он может быть лучшим выбором, если требуется сжать только один поток данных (а не несколько различных потоков). Ниже приведен пример сжатия одного файла:```java //: GZIPcompress.java // Uses GZIP compression in Java 1.1 to compress a file whose name is passed through the command line. import java.io.; import java.util.zip.;

```markdown
Публичный класс GZIPcompress {
  публичный статический void основной(строка[] аргументы) {
    попробовать {
      BufferedReader вход =
        новый BufferedReader(
          новый FileReader(аргументы[ Yö ]));
      BufferedOutputStream выход =
        новый BufferedOutputStream(
          новый GZIPOutputStream(
            новый FileOutputStream("test.gz")));
      выводить.println("Запись файла");
      целое с;
      пока ((с = вход.read()) != -1)
        выход.write(с);
      вход.close();
      выход.close();
      выводить.println("Чтение файла");
      BufferedReader вход2 =
        новый BufferedReader(
          новый InputStreamReader(
            новый GZIPInputStream(
              новый FileInputStream("test.gz"))));
      строка s;
      пока ((s = вход2.readLine()) != null)
        выводить.println(s);
    } catch(Исключение e) {
      e.printStackTrace();
    }
  }
}
///:~

Использование сжатия очень прямолинейно — достаточно обернуть выходной поток в `GZIPOutputStream` или `ZipOutputStream`, а входной поток — в `GZIPInputStream` или `ZipInputStream`. Остальные операции выполняются стандартными методами чтения и записи. Однако это типичный пример, когда нам приходится смешивать старые и новые потоки ввода/вывода: данные вводятся через класс `Reader`, а конструктор `GZIPOutputStream` принимает объект типа `OutputStream`, но не `Writer`.## Раздел 10.8.2 Сохранение нескольких файлов с помощью Zip

Библиотека Java 1.1 с поддержкой Zip кажется более полной. Она позволяет удобно сохранять несколько файлов. Даже существует отдельный класс для упрощения чтения Zip-файлов. Эта библиотека использует стандартный формат Zip, поэтому она хорошо работает со всеми распространенными компрессорами и декомпрессорами на Интернете. В этом примере используется тот же формат, что и в предыдущем, но он позволяет контролировать произвольное количество параметров командной строки. Кроме того, этот пример демонстрирует использование класса Checksum для вычисления и проверки контрольной суммы файла (Checksum). Можно выбрать между двумя типами контрольной суммы: Adler32 (быстрее) и CRC32 (медленнее, но более точный).

//: ZipCompress.java
// Использует сжатие Zip Java 1.1 для сжатия
// любого количества файлов, чьи имена передаются
// в качестве параметров командной строки.
import java.io.*;
import java.util.*;
import java.util.zip.*;
``````java
public class ZipCompress {
    public static void main(String[] args) {
        try {
            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");
            // Невозможно прочитать вышеуказанное примечание, хотя
            for (int i = 0; i < args.length; i++) {
                System.out.println("Запись файла " + 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("Контрольная сумма: " +
                               csum.getChecksum().getValue());
            // Теперь извлекаем файлы:
            System.out.println("Чтение файла");
            FileInputStream fi =
                new FileInputStream("test.zip");
            CheckedInputStream csumi =
                new CheckedInputStream(fi, new Adler32());
            ZipInputStream in2 =
                new ZipInputStream(new BufferedInputStream(csumi));
            ZipEntry ze;
            System.out.println("Контрольная сумма: " +
                               csumi.getChecksum().getValue());
            while ((ze = in2.getNextEntry()) != null) {
                System.out.println("Чтение файла " + ze);
                int x;
                while ((x = in2.read()) != -1)
                    System.out.write(x);
            }
            in2.close();
            // Альтернативный способ открытия и чтения
            // архива ZIP:
            ZipFile zf = new ZipFile("test.zip");
            Enumeration e = zf.entries();
            while (e.hasMoreElements()) {
                ZipEntry ze2 = (ZipEntry) e.nextElement();
                System.out.println("Файл: " + ze2);
                // ... и извлечение данных так же как раньше
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

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

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

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

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

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

Метод 10.8.3 Java Архив (jar) УтилитаФормат ZIP также используется в формате JAR (Java ARchive) файлов, введенном в Java 1.1. Эта форма файла предназначена для объединения нескольких файлов в один сжатый файл, аналогично ZIP. Однако, как и всё остальное в Java, JAR-файлы являются кросс-платформенными, поэтому нет необходимости беспокоиться о платформозависимых вопросах. Вместе со звуковыми и графическими файлами, в JAR-файле могут находиться и классовые файлы. При работе с интернет-приложениями JAR-файлы оказываются особенно полезными. До появления JAR-файлов веб-браузеры должны были многократно обращаться к веб-серверу для загрузки всех файлов, составляющих "小程序" (апплет). Кроме того, каждый файл был незакомпрессированным. Однако после объединения всех этих файлов в один JAR-файл требуется всего одно обращение к удалённому серверу. При этом благодаря использованию компрессии все данные можно получить быстрее. К тому же каждое входное содержание (элемент) в JAR-файле может быть защищено цифровой подписью (подробнее см. документацию Java для пользователей).

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

jar [опции] имя_файла [манифест] входной_файл

Опции представлены рядом букв (не требуется указывать дефис или любые другие знаки):

c Создание нового или пустого архива
t Вывод содержимого архива
x Распаковка всех файлов
u Распаковка указанного файла
f Указывает, что вы предоставите имя файла. Если этот параметр пропущен, jar считает, что его входные данные приходят из стандартного ввода; либо при создании файла, выходные данные будут отправлены в стандартный вывод
m Указывает, что первый параметр будет именем пользовательского манифеста
v Генерация подробного вывода, предоставляющего детальное описание работы программы jar
e Добавление главного класса в манифест
O Сохранение файлов без сжатия (для создания JAR-файла, который можно поместить в свой классический путь)
M Отключение автоматического создания манифеста

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

Ниже приведены некоторые типичные вызовы программы jar:

jar cf myJarFile.jar *.class

Создание JAR-файла с именем myJarFile.jar, содержащего все файлы .class в текущем каталоге, а также автоматически созданного манифеста.``` jar cmf myJarFile.jar myManifestFile.mf *.class


Аналогичным образом, но с добавлением пользовательского манифеста с именем `myManifestFile.mf`.

jar tf myJarFile.jar


Вывод списка всех файлов внутри JAR-файла `myJarFile.jar`.

jar tvf myJarFile.jar


Добавление флага `verbose` (подробный), чтобы предоставить более подробную информацию о файлах внутри JAR-файла `myJarFile.jar`.

jar cvf myApp.jar audio classes image


Предположим, что `audio`, `classes` и `image` являются подкаталогами, таким образом, все подкаталоги объединяются в файл `myApp.jar`. Также используется флаг `verbose`, чтобы получить более подробную информацию о работе программы `jar`.
Если JAR-файл создан с использованием опции `-O`, его можно поместить в свой классовый путь (`CLASSPATH`):

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

Java сможет искать цели в файлах lib1.jar и lib2.jar.

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

Как вы увидите в главе 13, мы также используем JAR для упаковки Java Beans.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-thinking-in-java-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-thinking-in-java-zh.git
oschina-mirror
wizardforcel-thinking-in-java-zh
wizardforcel-thinking-in-java-zh
master