Философия Java3
Шрифт:
Классы ввода/вывода удобно разделить по категориям, в зависимости от их функций. В Java 1.0 разработчики решили, что все, связанное с вводом данных, должно быть производным от базового класса InputStream, а все, имеющее отношение к выводу данных, — от класса OutputStream.
Как обычно, я постараюсь привести общий обзор этих классов, но за полными описаниями и списками методов каждого класса следует обращаться к документации JDK.
Типы InputStream
Назначение базового класса InputStream — представлять классы, которые получают данные из различных источников. Такими источниками могут быть:
• массив
• строка (String);
• файл;
• «канал» (pipe): данные помещаются с одного «конца» и извлекаются с другого;
• последовательность различных потоков, которые можно объединить в одном потоке;
• другие источники (например, подключение к Интернету).
С каждым из перечисленных источников связывается некоторый подкласс базового класса InputStream (табл. 16.1). Существует еще класс FilterlnputStream, который также является производным классом InputStream и представляет собой основу для классов-«надстроек», наделяющих входные потоки полезными свойствами и интерфейами. Его мы обсудим чуть позже.
Таблица 16.1. Разновидности входных потоков InputStream
Класс Назначение Аргументы конструктора,
порядок применения
Позволяет использовать буфер в памяти (массив байтов) в качестве источника данных для входного потока
ByteArraylnputStream
StringBufferlnputStream
FilelnputStream
PipedlnputStream
SequencelnputStream
FilterlnputStream
Превращает строку (String) во входной поток данных InputStream
Для чтения информации из файла
Производит данные, записываемые в соответствующий выходной поток PipedOutputStream. Реализует понятие канала
Сливает два или более потока InputStream в единый поток
Абстрактный класс, предоставляющий интерфейс для классов-надстроек, которые добавляют к существующим потокам полезные свойства
Буфер, из которого читаются байты. Как источник данных. Присоедините поток к классу FilterlnputStream, чтобы получить расширенные возможности
Строка. Лежащая в основе класса реализация на самом деле использует класс StringBuffer. Как источник данных. Присоедините поток к классу FilterlnputStream, чтобы получить расширенные возможности
Строка (String) с именем файла или объекты File и FileDescriptor. Как источник данных. Присоедините поток к классу FilterlnputStream, чтобы получить расширенные возможности
Объект PipedOutputStream. Как источник данных в многозадачном окружении. Присоедините поток к классу FilterlnputStream, чтобы получить расширенные возможности Два объекта-потока InputStream или перечисление Enumeration для контейнера, в котором содержатся все потоки.
Как источник данных. Присоедините поток к классу FilterlnputStream, чтобы получить расширенные возможности См. табл. 16.3
Типы OutputStream
В данную категорию (табл. 16.2) попадают классы, определяющие, куда направляются ваши данные: в массив байтов (но не напрямую в String; предполагается, что вы сможете
создать их из массива байтов), в файл или в канал.Вдобавок класс FilterOutputStream предоставляет базовый класс для клас-сов-«надстроек», которые способны наделять существующие потоки новыми полезными атрибутами и интерфейсами. Подробности мы отложим на потом.
Таблица 16.2. Разновидности выходных потоков OutputStream
Аргументы конструктора, порядок применения
Класс
Назначение
ByteArrayOutputStream Создает буфер в памяти. Все
данные, посылаемые в этот поток, размещаются в созданном буфере
FileOutputStream
PipedOutputStream
FilterOutputStream
Отправка данных в файл на диске
Все данные, записываемые в поток, автоматически появляются как входные данные в ассоциированном потоке PipedlnputStream. Реализует понятие канала
Абстрактный класс, предоставляющий интерфейс для классов-надстроек, которые добавляют к существующим потокам полезные свойства
Начальный размер буфера (не обязательно). Задает приемник данных. Присоедините поток к объекту FilterOutputStream, чтобы получить расширенные возможности Строка с именем файла или объекты File или FileDescriptor. Задает приемник данных. Присоедините этот поток к объекту FilterOutputStream, чтобы получить расширенные возможности Объект PipedlnputStream. Задает приемник данных в многозадачном окружении. Присоедините этот поток к объекту FilterOutputStream, чтобы получить расширенные возможности См. табл. 16.4
Добавление атрибутов и интерфейсов
«Наслаивание» дополнительных объектов для получения новых свойств и функций у определенных объектов называется надстройкой, или декоратором22. В библиотеке ввода/вывода Java постоянно требуется совмещение нескольких свойств, поэтому в ней и используются надстройки. Существование в библиотеке ввода/вывода Java классов-фильтров объясняется тем, что абстрактный класс фильтра является базвовым классом для всех существующих надстроек. (Надстройка должна включать в себя интерфейс «декорируемого» объекта, но расширение этого интерфейса также не запрещено и практикуется некоторыми классами-«фильтрами».)
Однако у такого подхода есть свои недостатки. Надстройки предоставляют дополнительную гибкость при написании программы (можно легко совмещать различные атрибуты), но при этом код получается излишне сложным. Некоторое неудобство библиотеки ввода/вывода Java объясняется тем, что для получения желаемого объекта приходится создавать много дополнительных объектов — «ядро» ввода/вывода и несколько надстроек.
Интерфейс для надстроек предоставляют классы FilterlnputStream (для входных потоков) и FilterOutputStream (для выходных потоков). Это абстрактные классы, производные от основных базовых классов библиотеки ввода/вывода InputStream и OutputStream. Наследование от этих классов — основное требование к классу-надстройке (поскольку таким образом обеспечивается общий интерфейс для «наслаиваемых» объектов).