— Привет, Амиго!

— Привет, Элли!

— Сегодня мы будем изучать потоки ввода-вывода.

— Да, я уже там все знаю. Это делается с помощью классов FileInputStream и FileOutputStream.

— Да, а какие методы есть у этих классов, знаешь?

— Конечно, вот методы FileInputStream:

Метод Описание
int read() Читает один байт и возвращает его.
int read(byte b[]) Читает массив байт, возвращает количество.
int read(byte b[], int off, int len) Читает из потока массив байт.
long skip(long n) Пропускает n байт, используется при чтении из потока.
int available() Возвращает количество байт, которое еще можно прочитать из потока.
void close() Закрывает поток.

— Все верно! А методы FileOutputStream?

— Вот:

Метод Описание
void write(int b) Записывает один байт в поток.
void write(byte b[]) Записывает массив байт в поток.
void write(byte b[], int off, int len) Записывает массив байт в поток.
void close() Закрывает поток.

— Амиго, ты меня удивляешь!

— А то!

— Отлично, тогда дам тебе два новых класса ZipInputStream и ZipOutputStream.

FileInputStream, FileOutputStream, ZipOutputStream, ZipInputStream - 1

— Zip? Это как zip-архив?

— Именно. Эти потоки предназначены для работы с файлами, которые являются zip-архивами. С помощью них можно что-то читать прямо из zip-фала или писать в него!

— Ух ты! Как интересно. Но ведь в zip-архиве может быть не один файл, как же они работают?

— А для этого есть еще один специальный класс – ZipEntry. Он представляет файл, хранящийся в архиве. Из ZipInputStream можно читать только объекты типа ZipEntry, а в ZipOutputStream можно писать только объекты ZipEntry. А вот сами ZipEntry как раз можно читать и писать как обычные файлы.

— А можно пример, как это работает?

— Конечно, вот пример, где мы создаем архив и кладем в него файл:

Код
// создаем архив
FileOutputStream zipFile = new FileOutputStream("c:/archive.zip");
ZipOutputStream zip = new ZipOutputStream(zipFile); 

//кладем в него ZipEntry – «архивный объект»
zip.putNextEntry(new ZipEntry("document.txt")); 

//копируем файл «document-for-archive.txt» в архив под именем «document.txt»
File file = new File("c:/document-for-archive.txt");
Files.copy(file.toPath(), zip);

// закрываем архив
zip.close();

— Как интересно. А разархивировать файлы так же легко?

— Ага. Вот тебе краткое описание методов классов ZipEntryZipInputStream и ZipOutputStream

ZipInputStream – это поток, поэтому все ZipEntry могут быть прочитаны только последовательно. Вот его методы:

Метод Описание
ZipEntry getNextEntry() Возвращает объект, описывающий следующий ZipEntry (пропускает все байты текущего entry).
void closeEntry() Закрывает чтение текущего ZipEntry (пропускает все байты текущего entry).
int available() Возвращает 1, если есть доступные ZipEntry, иначе 0.
int read(byte[] b, int off, int len) Читает байты из текущего ZipEntry.
long skip(long n) Пропускает n байт при чтении из потока.
void close() Закрывает поток.

— Не очень понятно.

— Лучше всего — это представить, что ты читаешь текстовый файл, а ZipEntry – это строки в нем. Можно читать как данные текущей строки – текущий ZipEntry, так и прыгать по строкам – getNextEntrycloseEntry.

— Вроде понятно, хотя не уверен, что правильно.

— ZipOutputStream и его методы:

Метод Описание
void setComment(String comment) Устанавливает комментарий к архиву.
void setMethod(int method) Указывает метод (тип) сжатия.
void setLevel(int level) Указывает степень сжатия. Чем сильнее, тем медленнее.
void putNextEntry(ZipEntry e) Добавляет новый ZipEntry.
void closeEntry() Закрывает текущий ZipEntry.
void write(byte[] b, int off, int len) Пишет набор байт в текущий ZipEntry.
void close() Закрывает поток.

— А мы же в примере выше почти ничего этого не использовали.

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

— Гм. Тоже не плохо. А ZipEntry?

— Ага. В ZipEntry дополнительно хранится только служебная информация:

Метод Описание
String getName() Внутреннее имя файла.
long getTime(), setTime(long) Время последней модификации entry.
long getCrc(), setCrc(long) Контрольная сумма.
long getSize(), setSize(long) Размер до компрессии.
int getMethod(), setMethod(int) Метод сжатия.
long get/setCompressedSize() Размер после архивации.
boolean isDirectory() Является ли entry директорией.

— Выглядит несложно и интересно, что не может не радовать!

— Отлично, тогда Диего даст тебе задачи и на эту тему.

— Язык мой – враг мой.