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

— Привіт, Еллі!

— Сьогодні ми вивчатимемо потоки введення-виведення.

— Так, я вже там усе знаю. Це робиться за допомогою класів 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 = новий 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 директорією.

— Виглядає нескладно та цікаво, що не може не радувати!

— Відмінно, тоді Дієго дасть тобі завдання і на цю тему.

— Мова моя – ворог мій.