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

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

Напрямую взаимодействует с каналом только буфер Byte Buffer, то есть буфер, хранящий простые байты. Если вы просмотрите документацию JDK для класса java.nio.ByteBuffer, то увидите что он достаточно прост: вы создаете его, указывая, сколько места надо выделить под данные. Класс содержит набор методов для получения и помещения данных в виде последовательности байтов или в виде примитивов. Однако возможности записать в него объект или даже простую строку нет. Буфер работает на достаточно низком уровне, поскольку обеспечивается более эффективная совместимость с большинством операционных систем.

Три

класса из «старой» библиотеки ввода/вывода были изменены так, чтобы они позволяли получить канал FileChannel: это FilelnputStream, FileOutput-Stream и RandomAccessFile. Заметьте, что эти классы манипулируют байтами, что согласуется с низкоуровневой направленностью nio. Классы для символьных данных Reader и Writer не образуют каналов, однако вспомогательный класс java.nio.channels.Channels имеет набор методов, позволяющих получить объекты Reader и Writer для каналов.

Простой пример использования всех трех типов потоков. Создаваемые каналы поддерживают запись, чтение/запись и только чтение:

//: io/GetChannel java // Получение каналов из потоков import java.nio.*, import java.nio channels *, import java io *;

public class GetChannel {

private static final int BSIZE = 1024; public static void main(String[] args) throws Exception { // Запись файла FileChannel fc =

new FileOutputStreamCdata.txt") getChannelО; fc write(ByteBuffer.wrap("Some text ".getBytesO)); fc. closeO,

// Добавление в конец файла fc =

new RandomAccessFileC'data.txt", "rw") getChannelО; fc position(fc.sizeO); // Переходим в конец fc write(ByteBuffer.wrap("Some more" getBytesO)), fc closeO; // Чтение файла;

fc = new FilelnputStreamC'data txt").getChannelО; ByteBuffer buff = ByteBuffer.allocate(BSIZE); fc.read(buff), buff .flipO;

while(buff .hasRemainingO)

System.out.print((char)buff getO);

}

} /* Output; Some text Some more *///:-

Для любого из рассмотренных выше классов потоков метод getChannel выдает канал FileChannel. Канал довольно прост: ему передается байтовый буфер ByteBuffer для чтения и записи, и вы можете заблокировать некоторые участки файла для монопольного доступа (этот процесс будет описан чуть позже).

Для помещения байтов в буфер ByteBuffer используется один из нескольких методов для записи данных (put); данные записываются в виде одного или нескольких байтов или значений примитивов. Впрочем, как было показано в примере, можно «заворачивать» уже существующий байтовый массив в буфер ByteBuffer, используя метод wrap. Когда вы так делаете, байтовый массив не копируется, а используется как хранилище для полученного буфера ByteBuffer. В таких случаях говорят, что буфер ByteBuffer создается на базе массива.

Файл data.txt заново открывается с помощью класса RandomAccessFile. Заметьте, что канал FileChannel может перемещаться внутри файла; в нашем примере он сдвигается в конец файла так, чтобы дополнительные записи присоединялись за существующим содержимым.

Чтобы доступ к файлу ограничивался только чтением, следует явно получить байтовый буфер ByteBuffer статическим методом allocate. Предназначение nio — быстрое перемещение большого количества данных, поэтому размер

буфера имеет значение: на самом деле установленный в примере размер в 1 килобайт меньше, чем обычно требуется (поэкспериментируйте с работающим приложением, чтобы найти оптимальное решение).

Можно получить еще большее быстродействие, используя вместо метода allocate метод allocateDirect. Он производит буфер «прямого доступа», еще теснее привязанный к низкоуровневой работе операционной системы. Однако такой буфер требует больше ресурсов, а реализация его различается в различных операционных системах. Опять же, поэкспериментируйте со своим приложением и выясните, дадут ли буферы прямого доступа лучшую производительность.

После вызова метода read буфера FileChannel для сохранения байтов в буфере ByteBuffer также необходимо вызвать для буфера метод flip, позволяющий впоследствии извлечь из буфера его данные (да, все это выглядит немного неудобно, но помните, что расчет делался на высокое быстродействие, поэтому все делается на низком уровне). И если затем нам снова понадобится буфер для чтения, придется вызывать перед каждым методом read метод clear. В этом нетрудно убедиться на примере простой программы копирования файлов:

//• io/ChannelCopy java

// Копирование файла с использованием каналов и буферов

// {Параметры Channel Copy java test txt}

import java nio *.

import java nio.channels *.

import java io *,

public class ChannelCopy {

private static final int BSIZE = 1024, public static void main(String[] args) throws Exception { if(args length != 2) {

System out println("параметры Источник Приемник"), System exit(l);

}

FileChannel

in = new FileInputStream(args[0]).getChannelО. out = new FileOutputStream(args[l]).getChannelО, ByteBuffer buffer = ByteBuffer.allocate(BSIZE); while(in read(buffer) != -1) {

buffer flipO; // Подготовка к записи out.write(buffer):

buffer.clear; // Подготовка к чтению

}

}

} /// ~

В программе создаются два канала FileChannel: для чтения и для записи. Выделяется буфер ByteBuffer, а когда метод FileChannel.read возвращает -1, это значит, что мы достигли конца входных данных (без сомнения, пережиток UNIX и С). После каждого вызова метода read, помещающего данные в буфер, метод flip подготавливает буфер так, чтобы информация из него могла быть извлечена методом write. После вызова write информация все еще хранится в буфере, поэтому метод clear перемещает все его внутренние указатели, чтобы буфер снова был способен принимать данные в методе read.

Впрочем, рассмотренная программа не лучшим образом выполняет копирование файлов. Специальные методы, transferTo и transferFrom, позволяют напрямую присоединить один канал к другому:

// io/TransferTo java

// Использование метода transferToO для соединения каналов // {Параметры TransferTo java TransferTo txt} import java nio channels.*, import java io *.

public class TransferTo {

public static void main(String[] args) throws Exception { if(args length != 2) {

System out printin("параметры источник приемник"), System exit(l).

Поделиться:
Популярные книги

Морской волк. 1-я Трилогия

Савин Владислав
1. Морской волк
Фантастика:
альтернативная история
8.71
рейтинг книги
Морской волк. 1-я Трилогия

Изменяющий-Механик. Компиляция. Книги 1-18

Усманов Хайдарали
Собрание сочинений
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
Изменяющий-Механик. Компиляция. Книги 1-18

Кодекс Крови. Книга IХ

Борзых М.
9. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга IХ

Государь

Кулаков Алексей Иванович
3. Рюрикова кровь
Фантастика:
мистика
альтернативная история
историческое фэнтези
6.25
рейтинг книги
Государь

Отход

Видум Инди
4. Петя и Валерон
Фантастика:
рпг
аниме
попаданцы
5.00
рейтинг книги
Отход

Эволюционер из трущоб. Том 6

Панарин Антон
6. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Эволюционер из трущоб. Том 6

Вечный. Книга IV

Рокотов Алексей
4. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга IV

Камень. Книга восьмая

Минин Станислав
8. Камень
Фантастика:
фэнтези
боевая фантастика
7.00
рейтинг книги
Камень. Книга восьмая

Кодекс Охотника. Книга XVIII

Винокуров Юрий
18. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XVIII

Третий. Том 3

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий. Том 3

Мистика

Гейман Нил
Детективы:
классические детективы
исторические детективы
7.29
рейтинг книги
Мистика

Родословная. Том 5

Ткачев Андрей Юрьевич
5. Линия крови
Фантастика:
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Родословная. Том 5

Кодекс Охотника. Книга XXXVI

Винокуров Юрий
36. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXVI

Дважды одаренный. Том V

Тарс Элиан
5. Дважды одаренный
Фантастика:
аниме
альтернативная история
городское фэнтези
5.00
рейтинг книги
Дважды одаренный. Том V