Основы NIO
NIO
- (сокращение от New Input/Output
— новый ввод-вывод).
С версии 1.4 в Java предоставляется вторая система ввода-вывода под названием NIO.
В этой системе поддерживается канальный подход к операциям ввода-вывода, ориентированный на применение буферов. А в версии JDK 7 система ввода-вывода NIO была существенно расширена, и теперь она оказывает улучшенную поддержку средств обработки файлов и файловых систем. На самом деле, изменения в этой системе значительны, и поэтому она иногда обозначается термином NIO.2
.
Основные положения о системе ввода-вывода NIO.
Система ввода-вывода NIO построена на двух основополагающих элементах: буферах
и каналах
.
В буфере хранятся данные, а канал предоставляет открытое соединение с устройством ввода-вывода, например файлом или сокетом. То есть, для применения системы ввода-вывода NIO
нужно получить канал для устройства ввода-вывода и буфер для хранения данных. После этого можно обращаться с буфером, вводя или выводя данные по мере необходимости.
Буфера
Буфера определяются в пакете java.nio
. Все буфера являются подклассами, производными от класса Buffer
, в котором определяются основные функциональные возможности, характерные для каждого буфера, в том числе текущая позиция, предел и емкость.
текущая позиция
определяет индекс в буфере, с которого в следующий раз начнется операция чтения или записи данных. Текущая позиция перемещается после выполнения большинства операций чтения или записипредел
определяет значение индекса за позицией последней доступной ячейки в буфереемкость
определяет количество элементов, которые можно хранить в буфере. Часто предел равен емкости буфера. В классеBuffer
поддерживается также отметка и очистка буфера.
В нем есть ряд методов, приведем некоторые из них:
abstract Object array()
// Возвращает ссылку на массив, если вызывающий буфер поддерживается массивом, иначе генерирует исключение типа
// UnsupportedOperationException. Если же массив доступен только для чтения, то генерируется исключение типа
// ReadOnlyBufferException
final Buffer reset()
// Устанавливает текущую позицию в вызывающем буфере
// на установленной ранее метке. Возвращает ссылку на буфер
abstract boolean hasArray()
// Возвращает логическое значение true, если вызывающий
// буфер поддерживается массивом, доступным для чтения и записи, а иначе — логическое значение false
abstract boolean isReadOnly()
// Возвращает логическое значение true, если вызывающий
// буфер является буфером только для чтения, а иначе — логическое значение false
final int limit()
// Возвращает предел для вызывающего буфера
final int capacity()
// Возвращает количество элементов, которые можно хранить в вызывающем буфере
final Buffer clear()
// Очищает вызывающий буфер и возвращает ссылку на него
final Buffer flip()
// Задает текущую позицию в качестве предела для вызывающего буфера и затем устанавливает текущую позицию в нуль.
// Возвращает ссылку на буфер
final Buffer mark()
// Устанавливает метку и возвращает ссылку на вызывающий буфер
final Buffer position(int n)
// Задает текущую позицию буфера равной n. Возвращает ссылку на буфер
final Buffer rewind()
// Устанавливает текущую позицию в вызывающем буфере в нуль.
// Возвращает ссылку на буфер
От класса Buffer
происходят и другие классы конкретных буферов, где тип хранимых данных можно определить по их именам. Класс MappedByteBuffer
является производным от класса ByteBuffer
и используется для сопоставления файла с буфером
Все буфера предоставляют различные методы get()
и put()
, которые позволяют получать данные из буфера или вносить их в него. (метод put()
недоступен, если буфер предназначен только для чтения).
Во всех классах буферов поддерживаются методы, выполняющие различные операции с буфером. Например:
- с помощью метода
allocate()
можно вручную выделить оперативную память под буфер - с помощью метода
wrap()
- организовать массив в пределах буфера - с помощью метода
slice()
- создать подпоследовательность в буфере.
Также см. статью про каналы.