Большинство реальных прикладных программ На java не являются текстовыми консольными программами, а содержат графический пользовательский интерфейс (ГПИ), построенный на основе библиотек AWT, Swing или JavaFX для взаимодействия с пользователем, или же они являются веб-приложениями. Текстовые консольные программы отлично подходят в качестве учебных примеров, но они имеют весьма незначительное практическое применение. К тому же поддержка консольного ввода-вывода в java ограничена и не очень удобна в употреблении — даже в простейших программах. Таким образом, текстовый консольный ввод-вывод не имеет большого практического значения для программирования на java.
Несмотря на все сказанное выше, в java предоставляется сильная и универсальная поддержка файлового и сетевого ввода-вывода. Система ввода-вывода в Java целостна и последовательна. Если усвоить ее основы, то овладеть всем остальным будет очень просто.
Потоки ввода-вывода
В программах На java создаются потоки ввода-вывода. Поток ввода-вывода — это абстракция, которая поставляет или потребляет информацию. Поток ввода-вывода связан с физическим устройством через систему ввода-вывода в java. Все потоки ввода-вывода ведут себя одинаково, несмотря на отличия в конкретных физических устройствах, с которыми они связаны. Таким образом, одни и те же классы и методы ввода-вывода применимы к разнотипным устройствам. Это означает, что абстракция потока ввода может охватывать разные типы ввода: из файла на диске, клавиатуры или сетевого соединения. Аналогично поток вывода может обращаться к консоли, файлу на диске или сетевому соединению. Потоки ввода-вывода предоставляют ясный способ организации ввода-вывода, избавляя от необходимости разбираться в отличиях, например, клавиатуры от сети. В языке Java потоки ввода-вывода реализуются в пределах иерархии классов, определенных в пакете java.io
.
На заметку! Помимо потокового ввода-вывода, определенного в пакете
java.io
, в Java предоставляется также буферный и канальный ввод-вывод, определенный в пакетеjava.nio
и его подчиненных пакетах.
Потоки ввода-вывода байтов и символов
ВJava определяются два вида потоков ввода-вывода: байтов и символов. Потоки ввода-вывода байтов предоставляют удобные средства для управления вводом и выводом отдельных байтов. Эти потоки используются, например, при чтении и записи двоичных данных. Потоки ввода-вывода символов предоставляют удобные средства управления вводом и выводом отдельных символов. С этой целью в них применяется кодировка в Юникоде, допускающая интернационализацию. Кроме того, потоки ввода-вывода символов оказываются порой более эффективными, чем потоки ввода-вывода байтов.
В первоначальной версии Java 1.0 потоки ввода-вывода символов отсутствовали, и поэтому весь ввод-вывод имел байтовую организацию. Потоки ввода-вывода символов были внедрены в версии Java 1.1, сделав не рекомендованным к употреблению некоторые классы и методы, поддерживавшие ввод-вывод с байтовой организацией. Устаревший код, в котором не применяются потоки ввода-вывода байтов, встречается все реже, но иногда он все еще применяется. Как правило, устаревший код приходится обновлять, если это возможно, чтобы воспользоваться преимуществами потоков ввода-вывода символов.
Следует также иметь в виду, что на самом низком уровне весь ввод-вывод по- прежнему имеет байтовую организацию. А потоки ввода-вывода символов лишь предоставляют удобные и эффективные средства для обращения с символами. В последующих разделах дается краткий обзор потоков ввода-вывода с байтовой и символьной организацией.
Классы потоков ввода-вывода байтов
Потоки ввода-вывода байтов определены в двух иерархиях классов. На вершине этих иерархий находятся абстрактные классы InputStream
и OutputStream
. У каждого из этих абстрактных классов имеется несколько конкретных подклассов, в которых учитываются отличия разных устройств, в числе файлов на диске, сетевых соединений и даже буферов памяти. Классы потоков ввода-вывода байтов из пакета java.io
перечислены в табл. 1. Одни из этих классов описываются ниже. Не следует, однако, забывать о необходимости импортировать пакет java.io
, чтобы воспользоваться классами потоков ввода-вывода.
Таблица 1. Классы потоков ввода-вывода байтов из пакета java.io
Класс потока ввода-вывода | Назначение |
| Буферизированный поток ввода |
| Буферизированный поток вывода |
| Поток ввода, читающий байты из массива |
| Поток вывода, записывающий байты в массив |
| Поток ввода, содержащий методы для чтения данных стандартных типов, определенных в java |
| Поток вывода, содержащий методы для записи данных стандартных типов, определенных в java |
| Поток ввода, читающий данные из файла |
| Поток вывода, записывающий данные в файл |
| Реализует абстрактный класс InputStream |
| Реализует абстрактный класс OutputStream |
| Абстрактный класс, описывающий поток ввода |
| Поток ввода объектов |
| Поток вывода объектов |
| Абстрактный класс, описывающий поток вывода |
| Канал ввода |
| Канал вывода |
| Поток вывода, содержащий методы print() и printlnO |
| Поток ввода, поддерживающий возврат одного байта обратно в поток ввода |
| Поток ввода, состоящий из двух и более потоков ввода, данные из которых читаются по очереди |
В абстрактных классах InputStream
и OutputStream
определяется ряд ключевых методов, реализуемых в других классах потоков ввода-вывода. Наиболее важными среди них являются методы read()
и write()
, читающие и записывающие байты данных соответственно. Оба эти метода объявлены как абстрактные в классах Inputstream и OutputStream, а в производных классах они переопределяются.
Классы потоков ввода-вывода символов
Потоки ввода-вывода символов также определены в двух иерархиях классов. На вершине этих иерархий находятся два абстрактных класса — Reader и Writer. Эти абстрактные классы управляют потоками символов в Юникоде. Для каждого из них в java предусмотрен ряд конкретных подклассов. Классы потоков ввода-вывода символов перечислены в табл. 2.
Таблица 2. Классы потоков ввода-вывода символов из пакета java.io
Класс потока ввода-вывода | Назначение |
| Буферизированный поток ввода символов |
| Буферизированный поток вывода символов |
| Поток ввода, читающий символы из массива |
| Поток вывода, записывающий символы в массив |
| Поток ввода, читающий символы из файла |
| Поток вывода, записывающий символы в файл |
| Фильтрованный поток чтения |
| Фильтрованный поток записи |
| Поток ввода, преобразующий байты в символы |
| Поток ввода, подсчитывающий строки |
| Поток вывода, преобразующий символы в байты |
| Канал ввода |
| Канал вывода |
| Поток вывода, содержащий методы |
| Поток ввода, позволяющий возвращать символы обратно в поток ввода |
| Абстрактный класс, описывающий поток ввода символов |
| Поток ввода, читающий символы из строки |
| Поток вывода, записывающий символы в строку |
| Абстрактный класс, описывающий поток вывода символов |
В абстрактных классах Reader
и Writer
определяется ряд ключевых методов, реализуемых в других классах потоков ввода-вывода. Наиболее важными среди них являются методы read()
и write()
, читающие и записывающие байты данных соответственно. Оба эти метода объявлены как абстрактные в классах Reader
и Writer
, а в производных классах они переопределяются.
Предопределенные потоки ввода-вывода
Как вам должно быть уже известно, все программы на java автоматически импортируют пакет java.lang
. В этом пакете определен класс System
, инкапсулирующий некоторые свойства исполняющей среды Java. Используя некоторые из его методов, можно, например, получить текущее время и настройки различных параметров, связанных с системой. Класс System
содержит также три переменные предопределенных потоков ввода-вывода: in
, out
и err
. Эти переменные объявлены в классе System
как public
, static
и final
. Это означает, что они могут быть использованы в любой другой части прикладной программы без обращения к конкретному объекту класса System
.
Переменная System.out
ссылается на стандартный поток вывода. По умолчанию это консоль. Переменная System.in
ссылается на стандартный поток ввода, которым по умолчанию является клавиатура. А переменная System.err ссылается на стандартный поток вывода ошибок, которым по умолчанию также является консоль. Но эти стандартные потоки могут быть перенаправлены на любое совместимое устройство ввода-вывода.
Переменная System.in
содержит объект типа InputStream
, а переменные System.out
и System.err
содержат объекты типа PrintStream
. Это потоки ввода-вывода байтов, хотя они, как правило, используются для чтения символов с консоли и записи символов на консоль. Как будет показано далее, их можно, если требуется, заключить в оболочки потоков ввода-вывода символов.