Класс InputStream имеет следующий абстрактный метод: abstract int read(). Этот метод считывает один байт и возвращает либо считанный байт, либо -1, если наталкивается на конец потока входных данных. Разработчик конкретного класса потока входных данных может переопределять этот метод так, чтобы он предоставлял какую-то полезную функциональную возможность.
Например, в классе FileInputStream этот метод выполняет считывание одного байта из файла. System.in представляет собой переопределенный объект подкласса InputStream, который позволяет считывать информацию с клавиатуры.
У класса InputStream еще также имеются и неабстрактные методы для считывания массива байтов или для пропускания ряда байтов. Эти методы вызывают абстрактный метод read, благодаря чему подклассам нужно переопределять только один метод.Аналогичным образом, класс OutputStream определяет следующий абстрактный метод, который записывает один байт в место выходных данных:
1 |
abstract void write(int b) |
Как методы read, так и методы write блокируют доступ до тех пор, пока байты действительно не будут считаны или записаны. Это означает, что если к потоку данных не удается получить доступ мгновенно(что обычно происходит из-за занятности сетевого подключения), происходит блокирование текущего потока задач(thread). А это дает другим потокам задач возможность выполнять какую-то полезную работу, пока метод ожидает, когда поток данных снова станет доступным.
Программа для контроля работы торговых представителей http://www.terrasoft.ua/industry/fmcg. Автоматизация, управление трейд-маркетингом и мерчендайзингом.
Метод available позволяет проверять, какое количество байтов доступно для считывания в текущий момент. Это означает, что фрагмент кода, вроде того, что показан ниже, вряд ли будет приводить к блокировке:
1 2 3 4 5 6 |
int bytesAvailable = in.available(); if (bytesAvailable > 0) { byte[] data = new byte[bytesAvailable]; in.read(data); } |
По завершении процесса считывания или записи данных в поток нужно обязательно закрывать его путем вызова метода close. Такой вызов проводит к освобождению системных ресурсов, доступных в ограниченном количестве. В случае открытия приложением множества потоков без последующего их закрытия, ресурсы системы могут истощаться.
Помимо этого, закрытие потока входных данных еще также приводит и к очистке(flush) использовавшегося для него буфера: все символы, которые временно помещались в этот буфер с целью их последующей доставки уже сразу в виде большего пакета, рассылаются по пунктам назначения. В частности, если не закрыть файл, последний пакет байтов может быть так никогда и не доставлен. Выполнять сбрасывание выходных данных также можно и вручную с помощью метода flush.
Даже если класс потока предоставляет конкретные методы для работы с исходными функциями read и write, программисты приложений редко их используют. Для них интерес чаще представляют все-таки данные, содержащие числа, строки и объекты, а не исходные байты.
Поэтому в Java предлагается много классов потоков, которые наследуются от базовых классов InputStream и OutputStream и позволяют работать с данными именно в том виде, в котором обычно требуются программистам, а не просто на уровне байтов.