Стандартна бібліотека Java має вельми розвинені засоби виведення даних. Всі можливості виведення даних зосереджені в пакеті java.io.
Існують дві паралельні ієрархії класів виведення. OutputStream і Writer. Клас Writer введений в останніх версіях Java.
У даній статті розглядається питання використання потоків для виведення даних в файл. Ієрархії вихідних OutputStream потоків представлена на наступному малюнку.
Потік Stream - це абстрактне значення джерела або приймача даних, які здатні обробляти інформацію. Є два типи потоків: байтові і символьні. У деяких ситуаціях символьні потоки більш ефективні, ніж байтові. Класи, похідні від класів OutputStream або Writer. мають методи з іменами write () для запису одиночних байтів або масиву байтів (відповідають за виведення даних).
Клас OutputStream - це абстрактний клас, що визначає байтовий потоковий виведення.
Спадкоємці даного класу визначають куди направляти дані: в масив байтів, в файл або канал. З масиву байт можна створити текстову рядок String.
Методи класу OutputStream:
- void write (int b) записує один байт у вихідний потік. Аргумент цього методу має тип int, що дозволяє викликати write, передаючи йому вираз, при цьому не потрібно виконувати приведення його типу до byte.
- void write (byte b []) записує у вихідний потік весь зазначений масив байтів.
- void write (byte b [], int off, int len) записує в потік частина масиву len байтів, починаючи з елемента b [off].
- void flush () очищає будь-які вихідні буфери, завершуючи операцію виведення.
- void close () закриває вихідний потік. Наступні спроби записи в цей потік порушуватимуть IOException.
Клас ByteArrayOutputStream представляє потік виведення, який використовує масив байтів в якості місця виведення. Щоб створити об'єкт даного класу, можна використовувати один з його конструкторів:
Перший конструктор створює масив даних для зберігання байтів довжиною в 32 байта, а другий конструктор створює масив довжиною size.
Приклади використання класу ByteArrayOutputStream:
У класі ByteArrayOutputStream метод write записує в потік деякі дані (масив байтів). Цей масив байтів записується в об'єкті ByteArrayOutputStream в захищене поле buf, яке представляє також масив байтів (protected byte [] buf). Так як метод write може викликати виключення, то виклик цього методу поміщається в блок try..catch.
Використовуючи методи toString () і toByteArray (). можна отримати масив байтів buf у вигляді тексту або безпосередньо у вигляді масиву байт.
За допомогою методу writeTo можна перенаправити масив байт в інший потік. Даний метод в якості параметра приймає об'єкт OutputStream. в який проводиться запис масиву байт:
Для ByteArrayOutputStream не треба явно закривати потік за допомогою методу close.
Клас FileOutputStream створює об'єкт класу OutputStream, який можна використовувати для запису байтів в файл. Це основний клас для роботи з файлами. Створення нового об'єкта не залежить від того, чи існує заданий файл чи ні. Якщо файл відсутній, то буде створено новий файл. У разі спроби відкриття файлу, доступного тільки для читання, буде викликано виключення.
FileOutputStream має наступний конструктори:
Сенс конструкторів останнього зрозумілий з їх опису. Але є кілька нюансів:
- При відкритті файлу на запис, якщо файл не існує, то він буде створений.
- Якщо файл існує, то він буде повністю оновлений. Тобто якщо відкрити і відразу закрити файл, то вміст файлу буде знищено; реальний файл на диску стане нульової довжини.
- Винятком для попереднього правила є останній з конструкторів. Якщо третьому параметру append привласнити значення true, то можна буде дописувати в кінець файлу.
Будь-якої додаткової функціональності в порівнянні з базовим класом FileOutputStream не додають.
Клас BufferedOutputStream створює буфер для потоків виведення. Цей буфер накопичує виводяться байти без постійного звернення до пристрою. І коли буфер заповнений, проводиться запис даних.
Клас BufferedOutputStream в конструкторі приймає як параметр об'єкт OutputStream - в прикладі це файловий потік виведення FileOutputStream.
BufferedOutputStream Не додає багато нових функцій, він просто оптимізує дію потоку виводаі його слід використовувати для організації більш ефективного буферизованного виведення в потік.
Клас DataOutputStream дозволяє писати дані в потік через інтерфейс DataOutput, який визначає методи, що перетворюють елементарні значення в форму послідовності байтів. Такі потоки полегшують збереження в файлі двійкових даних.
Для запису кожного з примітивних типів призначений свій метод класу DataOutputStream:
- writeByte (int value) - записує в потік 1 байт
- writeChar (int value) - записує 2х-байтовое значення char
- writeInt (int value) - записує в потік цілочисельне значення int
- writeShort (int v) - записує в потік значення short
- writeFloat (float value) - записує в потік 4-байтовое значення float
- writeDouble (double value) - записує в потік 8-байтовое значення double
- writeBoolean (boolean value) - записує в потік Булевой однобайтовое значення
- writeLong (long value) - записує в потік значення long
- writeUTF (String value) - записує в потік рядок в кодуванні UTF-8
PrintStream є саме тим класом, який використовується для виведення інформації в консоль. Коли ми з допомогою виклику System.out.println () пишемо в консоль деяку інформацію, то тим самим використовується PrintStream, так як змінна out класу System являє об'єкт класу PrintStream, а метод println () - це метод класу PrintStream.
Але PrintStream можна використовувати для запису інформації в потік виводу. Наприклад, запишемо інформацію в файл:
В даному прикладі використовується конструктор PrintStream. який в якості параметра приймає потік виведення FileOutputStream. Можна було б також використовувати конструктор із зазначенням назви файлу для запису: PrintStream (String filename).
За допомогою методу println () проводиться запис інформації в вихідний потік - тобто в об'єкт FileOutputStream. У випадку з виведенням на консоль за допомогою System.out.println () в якості потоку виведення виступає консоль.
Для виведення інформації в вихідний потік PrintStream використовує такі методи:
Наступний код показує можливості використання форматованого виведення класу PrintStream:
Клас ObjectOutputStream використовується для сериализации об'єктів в потік. Серіалізация представляє процес запису стану об'єкта в потік, відповідно процес вилучення або відновлення стану об'єкта з потоку називається десеріалізацію. Серіалізация дуже зручна, коли йде робота зі складними об'єктами.
Для створення об'єкта ObjectOutputStream необхідно в конструктор передати потік, в який буде проводиться запис об'єктів.
Для запису даних ObjectOutputStream використовує ряд методів, серед яких можна виділити наступні: