Java: InputStream. Потоки ввода

Java, как и многие современные языки программирования, поддерживает реализацию потоков ввода данных. В Java InputStream является базовым классом для байтовых потоков. Данный класс является абстрактным, то есть в процессе работы программы мы не можем создавать его экземпляр. Однако в пакете io имеется множество классов, которые наследуют и расширяют функциональность InputStream. Чтобы использовать этот класс в своем коде, его нужно импортировать из пакета java.io.InputStream. Далее мы рассмотрим базовую функциональность, которую предоставляет класс InputStream, а также основные классы, реализующие его.

Методы класса InputStream

Прежде чем приступить к подробному изучению методов класса InputStream, следует упомянуть, что он реализует интерфейсы Closeable и AutoCloseable. Интерфейс Closeable говорит нам о том, что при завершении работы с потоком его необходимо обязательно закрыть. Делается это при помощи метода close(). Поскольку большинство методов класса InputStream в случае возникновения ошибки генерирует исключение типа IOException, все операции требуется проводить в блоке try, а метод close() выносить в блок finally, чтобы он сработал вне зависимости от результата работы в теле try.

Интерфейс AutoCloseable значительно сокращает объем технического кода, поскольку позволяет методу close() срабатывать автоматически и не добавлять в ваш код блок finally. Если вы используете седьмую или более позднюю версию Java, InputStream можно помещать в так называемый try с ресурсами, который все операции по закрытию потоков берет на себя.

Рассмотрим основные методы класса InputStream:

  • int available() – возвращает доступное для чтения количество байтов;
  • int read() – берет из ресурса текущий байт и возвращает его в целочисленном представлении; если все байты прочитаны, возвращает -1;
  • int read(byte[] буфер) – читает доступные байты в указанный буфер в виде массива типа byte (количество читаемых байтов равно размеру заданного буфера; возвращает количество байтов, которые удалось прочитать; если все доступные байты прочитаны, возвращает -1);
  • int read(byte[] буфер, int смещение, int количество байтов) – перегрузка предыдущего метода, делает то же самое, но с указанной в «смещении» позиции и читает столько, сколько задано в «количестве байтов»;
  • long skip(long количество байтов) – пропускает указанное количество байтов и возвращает фактическое количество пропущенных.

InputStream реализуется несколькими классами, предназначенными для работы с разными источниками и типами данных. Ниже представлено дерево наследования.

Чтение файлов

Байтовый поток для чтения информации из файлов реализуется классом FileInputStream. Для того чтобы открыть файл для чтения байтов, достаточно создать экземпляр данного класса, передав его конструктору имя файла в качестве аргумента. Если файла с переданным именем не существует, будет сгенерировано исключение типа FileNotFoundException.

В случае удачного открытия файла, работа с ним выполняется при помощи описанных выше методов, так как FileInputStream является наследником InputStream.

Чтение примитивных типов данных

В предыдущем примере описывалась работа с байтовыми значениями, которые можно интерпретировать как символы. Но как быть, если нам необходимо прочитать целочисленное, дробное или логическое значение? Для этого в Java InputStream косвенно расширяется классом DataInputStream. Данный класс является оболочкой для InputStream, который передается ему при создании в качестве аргумента конструктора. Такого рода поток читает данные в бинарном виде.

DataInputStream также реализует интерфейс DataInput и его методы для чтения примитивных типов данных. Ниже представлен список этих методов.

Названия методов говорят сами за себя – каждый из них предназначен для чтения определенного типа данных.

Буферизированный поток ввода

Буферизированный поток чтения данных реализуется классом BufferedInputStream в Java. InputStream заключается в оболочку этим классом. Данный класс дополняет поток буфером, что позволяет читать одновременно не один, а несколько байтов. Это дает возможность значительно повысить производительность операции. BufferedInputStream является непрямым потомком InputStream и, соответственно, наследует все указанные выше методы.

Данный класс имеет два конструктора:

  • BufferedInputStream(InputStream поток ввода);
  • BufferedInputStream(InputStream поток ввода, int размер буфера)

Из сигнатуры конструкторов можно понять, что первый устанавливает размер буфера по умолчанию, а во втором есть возможность задать его вручную.

Заключение

Мы рассмотрели основные реализации InputStream. Если вам нужно преобразовать полученные байты в строку, то в Java InputStream to String(), к сожалению, не перегружен, поэтому для этого придется использовать специальные утилиты, например IOUtils из библиотеки Apache Commons.

Комментарии