спочатку перетворити в набір байт, а потім ці байти записати у файл. Аналогічні дії здійснюються і в ситуації, коли потрібно зберегти об'єкт (тобто його стан) - перетворення в набір байт і подальша їх запис у файл. Зрозуміло, що при відновленні даних в обох розглянутих випадках проробляються зворотні дії - спочатку зчитується послідовність байт, а потім вона перетворюється в потрібний формат. p align="justify"> На малюнку 1 представлені ієрархії класів введення/виведення. Як і говорилося, всі типи поділені на дві групи. Представляють вхідні потоки класи успадковуються від InputStream, а вихідні - від OutputStream. br/>В
Рис. 1. Ієрархія класів введення/виведення. br/>
Класи InputStream і OutputStream-це базовий клас для потоків введення, тобто читання. Відповідно, він описує базові методи для роботи з байтовими потоками даних. Ці методи необхідні всім класам, які успадковуються від InputStream. p align="justify"> Найпростіша операція представлена ​​методом read () (без аргументів). Він є абстрактним і, відповідно, має бути визначений у класах-спадкоємців. Цей метод призначений для зчитування рівно одного байта з потоку, проте повертає при цьому значення типу int. У тому випадку, якщо зчитування сталося успішно, повертається значення лежить в діапазоні від 0 до 255 і являє собою отриманий байт (значення int містить 4 байти і виходить простим доповненням нулями в двійковому представленні). Зверніть увагу, що отриманий таким чином байт не володіє знаком і не знаходиться в діапазоні від -128 до +127, як примітивний тип byte в Java. Якщо досягнуто кінець потоку, тобто в ньому більше немає інформації для читання, то повертається значення дорівнює -1. p align="justify"> Якщо ж вважати з потоку дані не вдається через якихось помилок, або збоїв, буде кинуто виключення java.io.IOException. Цей клас успадковується від Exception, тобто його завжди необхідно обробляти явно. Справа в тому, що канали передачі інформації, будь то Internet або, наприклад, жорсткий диск, можуть давати збої незалежно від того, наскільки добре написана програма. А це означає, що потрібно бути готовим до них, щоб користувач не втратив потрібні дані. p align="justify"> Метод read () - це абстрактний метод, але саме з дотриманням усіх зазначених умов він повинен бути реалізований у класах-спадкоємців. p align="justify"> На практиці зазвичай доводиться зчитувати не один, а відразу кілька байт - тобто масив байт. Для цього використовується метод read (), де в якості параметрів передається масив byte []. При виконанні цього методу в циклі здійснюється виклик абстрактного методу read () (визначеного без параметрів) і результатами заповнюється переданий масив. Кількість байт, прочитуване таким чином, дорівнює довжині переданого масиву. Але при цьому може так вийти, що дані в потоці закінчаться ще до того, як буде заповнений весь масив. Тобто можлива ситуація, коли в потоці даних (байт) міститься менше, ніж довжина масиву. Тому метод повертає значення int, яке вказує, скільки байт було реально лічено. Зрозуміло, що це значення може бути від 0 до величини довжини переданого масиву. p align="justify"> Якщо ж ми спочатку хочемо заповнити не весь масив, а тільки його частину, то для цих цілей використовується метод read (), якому, крім масиву byte [], передаються ще два int значення. Перше - це позиція в масиві, з якою слід почати заповнення, друге - кількість байт, яке потрібно вважати. Такий підхід, коли для отримання даних передається масив і два int числа - offset (зсув) і length (довжина), є досить поширеним і часто зустрічається не тільки в пакеті java.io. p align="justify"> При виклику методів read () можливе виникнення такої ситуації, коли запитувані дані ще не готові до зчитування. Наприклад, якщо ми зчитуємо дані, що надходять з мережі, і вони ще просто не прийшли. У такому разі не можна сказати, що даних більше немає, але і вважати теж нема чого - виконання зупиняється на виклику методу read () і виходить "зависання". p align="justify"> Щоб дізнатися, скільки байт в потоці готове до зчитування, застосовується метод available (). Цей метод повертає значення типу int, яке показує, скільки байт в потоці готове до зчитування. При цьому не варто плутати кількість байт, готових до зчитування, з тією кількістю байт, які взагалі можна буде вважати з цього потоку. Метод available () повертає число - кількість байт, саме на даний момент готових до зчитування. p align="justify"> Коли робота з вхідним потоком даних закінчена, його слід закрити. Для цього викликається метод close (). Цим викликом будуть звільнені всі системні ресурси, пов'язані з потоком. p align="justify"> Точно так само, як InputStream - це базовий клас для потоків введення, клас OutputStream - це базовий клас для потоків виводу. p align="justify"> У класі OutputStream аналогічним чином визначаються три методи write () - один приймаючий в якості параметра int, другий - byte [] і третій - byte...