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

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

Жанры

Программирование на Java
Шрифт:

Файл открыт для записи

Записано: 3 байт

Выходной поток закрыт

Файл открыт для чтения

Готово к считыванию: 3 байт

Считано: 3 байт

1,2,3,

Входной поток закрыт

Пример 15.2.

При работе с FileInputStream метод available практически наверняка вернет длину файла, то есть число байт, сколько вообще из него можно считать. Но не стоит закладываться на это при написании программ, которые должны устойчиво работать на различных платформах,– метод available возвращает число байт, которое может быть на данный

момент считано без блокирования. Тот факт, что, скорее всего, это число и будет длиной файла, является всего лишь частным случаем работы на некоторых платформах.

В приведенном примере для наглядности закрытие потоков производилось сразу же после окончания их использования в основном блоке. Однако лучше закрывать потоки в finally блоке.

...

}

finally {

try {

inFile.close;

}

catch(IOException e) {};

}

Такой подход гарантирует, что поток будет закрыт и будут освобождены все связанные с ним системные ресурсы.

PipedInputStream и PipedOutputStream

Классы PipedInputStream и PipedOutputStream характеризуются тем, что их объекты всегда используются в паре – к одному объекту PipedInputStream привязывается (подключается) один объект PipedOutputStream. Они могут быть полезны, если в программе необходимо организовать обмен данными между модулями (например, между потоками выполнения).

Эти классы применяются следующим образом: создается по объекту PipedInputStream и PipedOutputStream, после чего они могут быть соединены между собой. Один объект PipedOutputStream может быть соединен с ровно одним объектом PipedInputStream, и наоборот. Затем в объект PipedOutputStream записываются данные, после чего они могут быть считаны именно в подключенном объекте PipedInputStream. Такое соединение можно обеспечить либо вызовом метода connect с передачей соответствующего объекта PipedI/OStream (будем так кратко обозначать пару классов, в данном случае PipedInputStream и PipedOutputStream ), либо передать этот объект еще при вызове конструктора.

Использование связки PipedInputStream и PipedOutputStream показано в следующем примере:

try {

int countRead = 0;

byte[] toRead = new byte[100];

PipedInputStream pipeIn = new PipedInputStream;

PipedOutputStream pipeOut = new PipedOutputStream(pipeIn);

// Считывать в массив, пока он полностью не будет заполнен

while(countRead<toRead.length) {

// Записать в поток некоторое количество байт

for(int i=0; i<(Math.random*10); i++) {

pipeOut.write((byte)(Math.random*127));

}

// Считать из потока доступные данные,

// добавить их к уже считанным.

int willRead = pipeIn.available;

if(willRead+countRead>toRead.length)

//Нужно считать только до предела массива

willRead = toRead.length-countRead;

countRead += pipeIn.read(toRead, countRead, willRead);

}

}

catch (IOException e) {

System.out.println ("Impossible IOException occur: ");

e.printStackTrace;

}

Пример 15.3.

Данный пример носит чисто демонстративный характер (в результате его работы массив toRead будет заполнен

случайными числами). Более явно выгода от использования PipedI/OStream в основном проявляется при разработке многопоточного приложения. Если в программе запускается несколько потоков исполнения, организовать передачу данных между ними удобно с помощью этих классов. Для этого нужно создать связанные объекты PipedI/OStream, после чего передать ссылки на них в соответствующие потоки. Поток выполнения, в котором производится чтение данных, может содержать подобный код:

// inStream - объект класса PipedInputStream

try {

while(true) {

byte[] readedBytes = null;

synchronized(inStream) {

int bytesAvailable = inStream.available;

readedBytes = new byte[bytesAvailable];

inStream.read(readedBytes);

}

// обработка полученных данных из readedBytes

// …

} catch(IOException e) {

/* IOException будет брошено, когда поток inStream, либо

связанный с ним PipedOutputStream, уже закрыт, и при этом

производится попытка считывания из inStream */

System.out.println("работа с потоком inStream завершена");

}

Пример 15.4.

Если с объектом inStream одновременно могут работать несколько потоков выполнения, то необходимо использовать блок synchronized (как и сделано в примере), который гарантирует, что в период между вызовами inStream.available и inStream.read(…) ни в каком другом потоке выполнения не будет производиться считывание из inStream. Поэтому вызов inStream.read(readedBytes) не приведет к блокировке и все данные, готовые к считыванию, будут считаны.

StringBufferInputStream

Иногда бывает удобно работать с текстовой строкой String как с потоком байт. Для этого можно воспользоваться классом StringBufferInputStream. При создании объекта этого класса необходимо передать конструктору объект String. Данные, возвращаемые методом read, будут считываться именно из этой строки. При этом символы будут преобразовываться в байты с потерей точности – старший байт отбрасывается (напомним, что символ char состоит из двух байт).

SequenceInputStream

Класс SequenceInputStream объединяет поток данных из других двух и более входных потоков. Данные будут вычитываться последовательно – сначала все данные из первого потока в списке, затем из второго, и так далее. Конец потока SequenceInputStream будет достигнут только тогда, когда будет достигнут конец потока, последнего в списке.

В этом классе имеется два конструктора – принимающий два потока и принимающий Enumeration (в котором, конечно, должны быть только экземпляры InputStream и его наследников). Когда вызывается метод read, SequenceInputStream пытается считать байт из текущего входного потока. Если в нем больше данных нет (считанное из него значение равно -1 ), у него вызывается метод close и следующий входной поток становится текущим. Так продолжается до тех пор, пока не будут получены все данные из последнего потока. Если при считывании обнаруживается, что больше входных потоков нет, SequenceInputStream возвращает -1. Вызов метода close у SequenceInputStream закрывает все содержащиеся в нем входные потоки.

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

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Город Богов

Парсиев Дмитрий
1. Профсоюз водителей грузовых драконов
Фантастика:
юмористическая фантастика
детективная фантастика
попаданцы
5.00
рейтинг книги
Город Богов

Звездная Кровь. Изгой II

Елисеев Алексей Станиславович
2. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
попаданцы
технофэнтези
рпг
5.00
рейтинг книги
Звездная Кровь. Изгой II

Измена. Жизнь заново

Верди Алиса
1. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Жизнь заново

Адвокат Империи 7

Карелин Сергей Витальевич
7. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 7

Магия чистых душ 2

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.56
рейтинг книги
Магия чистых душ 2

Идеальный мир для Лекаря 18

Сапфир Олег
18. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 18

Двойник Короля 5

Скабер Артемий
5. Двойник Короля
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Двойник Короля 5

Неудержимый. Книга XVII

Боярский Андрей
17. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XVII

Прометей: каменный век

Рави Ивар
1. Прометей
Фантастика:
альтернативная история
6.82
рейтинг книги
Прометей: каменный век

Барин-Шабарин

Гуров Валерий Александрович
1. Барин-Шабарин
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Барин-Шабарин

Развод с миллиардером

Вильде Арина
1. Золушка и миллиардер
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Развод с миллиардером

Курсант. На Берлин

Барчук Павел
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант. На Берлин

Мастеровой

Дроздов Анатолий Федорович
Фантастика:
фэнтези
боевая фантастика
альтернативная история
7.40
рейтинг книги
Мастеровой