Философия Java3
Шрифт:
Начальный размер буфера (не обязательно). Задает приемник данных. Присоедините поток к объекту FilterOutputStream, чтобы получить расширенные возможности Строка с именем файла или объекты File или FileDescriptor. Задает приемник данных. Присоедините этот поток к объекту FilterOutputStream, чтобы получить расширенные возможности Объект PipedlnputStream. Задает приемник данных в многозадачном окружении. Присоедините этот поток к объекту FilterOutputStream, чтобы получить расширенные возможности См. табл. 16.4
Добавление атрибутов и интерфейсов
«Наслаивание»
Однако у такого подхода есть свои недостатки. Надстройки предоставляют дополнительную гибкость при написании программы (можно легко совмещать различные атрибуты), но при этом код получается излишне сложным. Некоторое неудобство библиотеки ввода/вывода Java объясняется тем, что для получения желаемого объекта приходится создавать много дополнительных объектов — «ядро» ввода/вывода и несколько надстроек.
Интерфейс для надстроек предоставляют классы FilterlnputStream (для входных потоков) и FilterOutputStream (для выходных потоков). Это абстрактные классы, производные от основных базовых классов библиотеки ввода/вывода InputStream и OutputStream. Наследование от этих классов — основное требование к классу-надстройке (поскольку таким образом обеспечивается общий интерфейс для «наслаиваемых» объектов).
Чтение из InputStream с использованием FilterlnputStream
Классы, производные от FilterlnputStream (табл. 16.3), выполняют две различные миссии. DatalnputStream позволяет читать из потока различные типы простейших данных и строки. (Все методы этого класса начинаются с префикса read — например, readByte, readFloat и т. п.) Этот класс, вместе с «парным» классом DataOutputStream, предоставляет возможность направленной передачи простейших данных посредством потоков. Место доставки определяется классами, описанными в табл. 16.1.
Другие классы изменяют внутренние механизмы входного потока: применение буферизации, подсчет количества прочитанных строк (что позволяет запросить или задать номер строки), возможность возврата в поток только что прочитанных символов. Вероятно, последние два класса создавались в основном для построения компиляторов (то есть их добавили в библиотеку в процессе написания компилятора Java), и прока в повседневном программировании от них немного.
Ввод данных почти всегда осуществляется с буферизацией, вне зависимости от присоединенного устройства ввода/вывода, поэтому имеет смысл сделать отдельный класс (или просто специальный метод) не для буферизованного ввода данных, а, наоборот, для прямого.
Таблица 16.3.
Класс
Назначение
Аргументы конструктора, порядок применения
DatalnputStream
Используется в сочетании с классом DataOutputStream и позволяет читать примитивы
Входной поток InputStream. Содержит все необходимое для чтения всех простейших типов
Аргументы конструктора, порядок применения
Назначение
Класс
(целые (int, long), символы (char) и т. д.) из потока, без привязки к внутреннему представлению Используется для предотвращения физического обращения к устройству при каждом новом запросе данных
BufferedlnputStream
LineNumberlnputStream
PushbacklnputStream
Следит за количеством считанных из потока строк; вы можете узнать их число, вызвав метод getLineNumber, а также перейти к определенной строке с помощью метода setLineNumber(int) Имеет односимвольный буфер, который позволяет вернуть в поток только что прочитанный символ
Входной поток InputStream, размер буфера (необязательно). По существу, никакого интерфейса этот класс не предоставляет, он просто присоединяет к потоку буфер. Добавьте дополнительно объект, предоставляющий интерфейс Входной поток InputStream. Этот класс просто считывает строки, поэтому к нему стоит добавить еще одну, более полезную, надстройку
Входной поток InputStream. Обычно используется при сканировании файлов для компилятора. Скорее всего, вам он не понадобится
Запись в OutputStream с помощью FilterOutputStream
У класса DatalnputStream существует «парный» класс DataOutputStream (табл. 16.4), который позволяет форматировать и записывать в поток примитивы и строки таким образом, что на любой машине и на любой платформе их сможет прочитать и правильно обработать DatalnputStream. Все его методы начинаются с префикса write (запись): writeByte, writeFloat и т. п.
Класс PrintStream изначально был предназначен для вывода значений в формате, понятном для человека. В данном аспекте он отличается от класса DataOutputStream, потому что цель последнего — разместить данные в потоке так, чтобы DatalnputStream смог их правильно распознать.
Основные методы класса PrintStream — print и println, они перегружены для наиболее часто используемых типов. После вывода значения метод println осуществляет перевод на новую строку, в то время как метод print этого не делает.
На практике класс PrintStream довольно-таки неудобен, поскольку он перехватывает и скрывает все возбуждаемые исключения. (Приходится явно вызывать метод checkError, который возвращает true, если во время исполнения какого-либо из методов класса произошла ошибка.) К тому же этот класс как следует не интернационализован и не выполняет перевод строки платформ-но-независимым способом (все эти проблемы решены в классе PrintWriter, описанном ниже).