Что делает метод available java
Перейти к содержимому

Что делает метод available java

  • автор:

Потоки ввода, InputStream

Существуют две параллельные иерархии классов ввода : InputStream и Reader. Класс Reader введен в последних версиях Java. В данной статье рассматривается вопрос использования потока байтового ввода InputStream, иерархия которого представлена на следующем рисунке.

Иерархия InputStream

Поток Stream— это абстрактное понятие источника или приёмника данных, которые способны обрабатывать информацию. Есть два типа потоков: байтовые и символьные. В некоторых ситуациях символьные потоки более эффективны, чем байтовые. Классы, производные от базовых InputStream или Reader, имеют методы read() для чтения отдельных байтов или массива байтов.

Входной поток InputStream

Базовый класс InputStream — это абстрактный класс, определяющий входной поток данных, и является родителем для классов, получающих данные из различных источников : массив байтов, строки (String), файлы, каналы pipe, у которых одна из сторон является входом, а вторая сторона играет роль выхода, и т.д. Методы класса InputStream при возникновении ошибки вызывают исключение IOException.

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

Метод Описание
int read() возвращает очередной доступный символ во входном потоке в виде целого
int read(byte b[]) чтение b.length байтов из входного потока в массив b. Возвращает количество прочитанных из потока байтов
int read(byte b[], int off, int len) чтение len байтов в массиве b, начиная со смещения off. Возвращает количество реально прочитанных байтов
long skip(long n) пропуск во входном потоке n байтов. Возвращает количество пропущенных байтов
int available() получение количество доступных для чтения байтов
void close() закрытие источник ввода. Последующие попытки чтения из этого потока вызывают IOException
void mark(int readlimit) установка метки в текущей позиции входного потока, которую можно будет использовать до тех пор, пока из потока не будет прочитано readlimit байтов
void reset() перевод указателя потока на установленную ранее метку
boolean markSupported() проверка поддержки потоком операции mark/reset

Класс InputStream часто выступает в качестве параметров конструкторов или методов различных классов. Согласно правилам наследования это означает, что в качестве параметра может быть передан объект любого класса-наследника. Это позволяет комбинировать классы для достижения нужных нам целей.

ByteArrayInputStream

Класс ByteArrayInputStream использует байтовый массив в качестве источника данных. Он имеет следующие конструкторы :

ByteArrayInputStream(byte[] buf); ByteArrayInputStream(byte[] buf, int offset, int length);

В качестве параметров конструкторы ByteArrayInputStream используют массив байтов buf для чтения, смещение относительно начала массива offset и количество считываемых символов length.

Пример чтения массив байтов в консоль:

import java.io.ByteArrayInputStream; public class TestBIS < public static void main(String[] args) < byte[] array1 = new byte[]; ByteArrayInputStream bis1; bis1 = new ByteArrayInputStream(array1); int b; while((b = bis1.read()) != -1) System.out.println(b); String text = "Hello world!"; byte[] array2 = text.getBytes(); ByteArrayInputStream bis2; bis2 = new ByteArrayInputStream(array2, 0, 5); while((b = bis2.read()) != -1) System.out.println((char)b); > >

В отличие от других классов потоков для закрытия объекта ByteArrayInputStream не требует вызывать метод close.

FileInputStream

FileInputStream — основной класс из данной иерархии для работы с файлами. Имеет два основных конструктора.

FileInputStream(File file) throws FileNotFoundException; FileInputStream(String name) throws FileNotFoundException;

Подробно FileInputStream описан на странице Файлы и директории

FilterInputStream

FilterInputStream — абстрактный класс, предоставляющий интерфейс для классов-надстроек, которые добавляют к существующим потокам полезные свойства. FilterInputStream является базовым классом для двух других классов. Его единственный конструктор требует передачи в качестве параметра объекта класса InputStream, т.е. фактически объекта некоторого неабстрактного класса, порожденного от InputStream.

Прямое использование FilterInputStream в программе нецелесообразно.

BufferedInputStream

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

import java.io.*; public class TestBufferedInputStream < public static void main(String[] args) < String text = "Hello world!"; byte[] buffer = text.getBytes(); ByteArrayInputStream bais; bais = new ByteArrayInputStream(buffer); try < BufferedInputStream bis; bis = new BufferedInputStream(bais); int c; while((c = bis.read()) != -1)< System.out.print((char)c); >> catch(Exception e) < System.out.println(e.getMessage()); >> >

В конструкторе класса BufferedInputStream необходимо передать InputStream. В данном случае таким объектом является экземпляр класса ByteArrayInputStream.

Как и все потоки ввода BufferedInputStream обладает методом read(), который считывает данные с помощью метода read из массива buffer.

Фактические все то же самое можно было сделать и с помощью одного ByteArrayInputStream, не прибегая к буферизированному потоку. Класс BufferedInputStream просто оптимизирует производительность при работе с потоком ByteArrayInputStream.

DataInputStream

Для чтения байтовых данных (не строк) применяется класс DataInputStream. В этом случае необходимо использовать классы из группы InputStream. Для преобразования строки в массив байтов, пригодный для помещения в поток ByteArrayInputStream, в классе String предусмотрен метод getBytes(). Полученный ByteArrayInputStream представляет собой поток InputStream, подходящий для передачи DataInputStream.

При побайтовом чтении символов из форматированного потока DataInputStream методом readByte() любое полученное значение будет считаться действительным, поэтому возвращаемое значение неприменимо для идентификации конца потока. Вместо этого можно использовать метод available(), который сообщает, сколько еще осталось символов.

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

Конструктор класса DataInputStream:

DataInputStream(InputStream stream)

Методы DataInputStream

Метод Описание
boolean readBoolean() байт булевого однобайтового значения
byte readByte() байт одного байта
char readChar() байт значения char
double readDouble() байт восьмибайтового значения double
float readFloat() чтение четырехбайтового значения float
int readInt() чтение целочисленного значения int
long readLong() чтение значения long
short readShort() чтение значения short
String readUTF() чтение строки в кодировке UTF-8
int skipBytes(int n) пропуск при чтении n байтов

Пример чтения из бинарного файла с использованием DataInputStream

import java.io.*; public class TestDataInputStream < public static void main(String[] args) < // Считывание из бинарного файла data.bin объекта // типа Person try < DataInputStream dis; dis = new DataInputStream( new FileInputStream("data.bin")); String name = dis.readUTF(); int age = dis.readInt(); double height = dis.readDouble(); boolean married = dis.readBoolean(); System.out.printf("Человека зовут: %s ; " + "его возраст: %d , " + "его рост: %f метров, " + "женат/замужем: %b", name, age, height, married); >catch(IOException ex) < System.out.println(ex.getMessage()); >> >

ObjectInputStream

Класс ObjectInputStream отвечает за чтение ранее сериализованных данных из потока. В конструкторе он принимает ссылку на поток ввода:

ObjectInputStream(InputStream in)

Основные методы класса ObjectInputStream :

Метод Описание
int read() чтение одного байта; возвращает его целочисленное представление
boolean readBoolean() чтение одного значения boolean
byte readByte() чтение одного байта
char readChar() чтение одного символ char
double readDouble() чтение значения типа double
float readFloat() чтение значения типа float
int readInt() чтение целочисленного значения int
long readLong() чтение значения типа long
short readShort() чтение значения типа short
String readUTF() чтение строки в кодировке UTF-8
Object readObject() чтение объекта
int skipBytes(int len) пропуск при чтении нескольких байт, количество которых равно len
int available() чтение количества доступных для чтения байт
void close() закрытие потока

Пример чтения объекта Person из файла :

import java.io.*; public class TestObjectInputStream < public static void main(String[] args) < try < ObjectInputStream ois; ois = new ObjectInputStream( new FileInputStream("person.dat")); Person person = (Person) ois.readObject(); System.out.printf("Имя: %s \t Возраст: %d \n", person.name, person.age); >catch(Exception e) < System.out.println(e.getMessage()); >> class Person implements Serializable < private static final long serialVersionUID = 1L; public String name; public int age; public double height; public boolean married; public Person(String n, int a, double h, boolean m) < this.name = n; this.height = h; this.age = a; this.married = m; >> >

Класс PipedInputStream

Класс PipedInputStream — это специальный класс, используемый для связи отдельных программ (потоков) друг с другом внутри одной JVM. Данный класс является важным инструментом организации синхронизации потоков.

Конструкторы PipedInputStream :

PipedInputStream() PipedInputStream(int pipeSize) PipedInputStream (PipedOutputStream src) PipedInputStream (PipedOutputStream src, int pipeSize)

Методы PipedInputStream :

  • available()
  • close()
  • connect (PipedOutputStream src)
  • read()
  • read(byte[] b, int off, int len)
  • receive(int b)

Пример простого использования PipedInputStream :

InputStream input = new PipedInputStream (pipedOutputStream); int data = input.read(); while(data != -1) < // обработка данных в отдельном // методе doSomethingWithData doSomethingWithData(data); data = input.read(); >input.close();

В чем разница возвращаемого значения available() и read(byte[] b)

Считывая с файла потоком FileInputStream input получаем данные значения. Разве метод available не должен возвращать количество доступных битов так же как и вторая конструкция? файл содержит следующий текст:

Отслеживать
abbath0767
задан 19 ноя 2015 в 16:05
abbath0767 abbath0767
1,455 3 3 золотых знака 15 15 серебряных знаков 27 27 бронзовых знаков
input.read(new byte[input.read]) — опечатка, и должно быть input.read(new byte[input.read()]) ?
19 ноя 2015 в 16:18
Да, опечатка, благодарю
20 ноя 2015 в 7:49

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

  • .available() не блокирует поток выполнения при отсутствии данных , а .read() — блокирует.
  • .available() возвращает примерное количество доступных для чтения байтов, а .read(byte[] b) — количество считанных в буфер (массив байтов), от -1 при достижении конца потока данных и до размера массива ( b.length ).
  • .available() лишь проверяет наличие данных, а .read() — их считывает.

Как работает input.read(new byte[input.read()]) :

  1. Происходит считывание одного байта из потока с помощью input.read() .
  2. Его значение (в данном случае код символа j — 106 ), которое возвращает .read() (именно значение первого байта, а не количество байтов), используется для создания массива из 106 байтов.
  3. В данный байтовый массив считываются данные из потока.
  4. Данных в потоке оставалось 8 байтов (первый уже был считан в пункте 1), и в буфер они входят ( 106 > 8 ), так что .read(byte[] b) возвращает количество считанных байтов — 8.

Отслеживать
ответ дан 19 ноя 2015 в 20:19
19.1k 6 6 золотых знаков 30 30 серебряных знаков 44 44 бронзовых знака

Возможно я не верно понимаю, но в файле у меня 9 символов, соответственно ожидаемый результат — 9 байт. Метод .available() возвращает ожидаемый результат. Что именно я не учитываю в своих рассуждениях @regent ?

20 ноя 2015 в 8:04

И да, правильно ли я понимаю, что конструкция byte[] b = new byte[input.available()] — заведомо некорректна, для будущего использования метода .read()?

20 ноя 2015 в 8:28

@mamba0767 да, заведомо некорректна в том плане что это не даст гарантий, что вы прочитаете за раз все доступные байты. По поводу вашего примера из вопроса — обновил ответ, добавив объяснение того, что там происходит.

20 ноя 2015 в 9:30
а на Ваш взгляд данная конструкция оптимальна для простейшего побайтового чтения с файла?
20 ноя 2015 в 18:21

@mamba0767 для простейшего байтового чтения из файла я бы использовал int read = input.read(buffer); внутри while (read > 0) . Это, по-моему, лучше, чем читать по одному байту. Можно и всякие обёртки над InputStream использовать для, например, более удобного, построчного чтения из текстового файла.

Что делает метод available java

Этот абстрактный класс является суперклассом всех классов, представляющих входной поток байтов. Приложения, которые должны определить подкласс InputStream должен всегда обеспечивать метод, который возвращает следующий байт ввода.

Сводка конструктора

Конструкторы

Конструктор и Описание
InputStream()

Сводка метода

Методы

Модификатор и Тип Метод и Описание
int available()

Возвращает оценку числа байтов, которые могут быть считаны (или перескочиться) от этого входного потока, не блокируя следующим вызовом метода для этого входного потока.

Завершения этот входной поток и выпуски любые системные ресурсы связались с потоком.
Отмечает текущую позицию в этом входном потоке.
Тесты, если этот входной поток поддерживает mark и reset методы.
Читает следующий байт данных от входного потока.
Чтения некоторое число байтов от входного потока и хранят их в буферный массив b .
Чтения до len байты данных от входного потока в массив байтов.

Репозиции этот поток к позиции в это время mark метод был последним, обращался к этому входному потоку.

Перескакивает и отбрасывает n байты данных от этого входного потока.

Методы java.lang унаследованный от класса. Объект

Деталь конструктора

InputStream
public InputStream()

Деталь метода

читать

Читает следующий байт данных от входного потока. Байт значения возвращается как int в диапазоне 0 к 255 . Если никакой байт не доступен, потому что конец потока был достигнут, значение -1 возвращается. Этот метод блоки до входных данных доступен, конец потока обнаруживается, или исключение выдается. Подкласс должен обеспечить реализацию этого метода.

читать

Чтения некоторое число байтов от входного потока и хранят их в буферный массив b . Число байтов фактически чтение возвращается как целое число. Этот метод блоки до входных данных доступен, конец файла обнаруживается, или исключение выдается. Если длина b нуль, тогда никакие байты не читаются и 0 возвращается; иначе, есть попытка считать по крайней мере один байт. Если никакой байт не доступен, потому что поток в конце файла, значения -1 возвращается; иначе, по крайней мере один байт читается и сохранен в b . Первое побайтовое чтение сохранено в элемент b[0] , следующий в b[1] , и так далее. Число чтения байтов, самое большее, равно длине b . Позвольте k быть числом байтов фактически чтение; эти байты будут сохранены в элементах b[0] через b[ k -1] , отъезд элементов b[ k ] через b[b.length-1] незатронутый. read(b) метод для класса InputStream имеет тот же самый эффект как:

 read(b, 0, b.length) 
читать

Чтения до len байты данных от входного потока в массив байтов. Попытка предпринимается, чтобы читать столько, сколько len байты, но меньшее число могут быть считаны. Число байтов фактически чтение возвращается как целое число. Этот метод блоки до входных данных доступен, конец файла обнаруживается, или исключение выдается. Если len нуль, тогда никакие байты не читаются и 0 возвращается; иначе, есть попытка считать по крайней мере один байт. Если никакой байт не доступен, потому что поток в конце файла, значения -1 возвращается; иначе, по крайней мере один байт читается и сохранен в b . Первое побайтовое чтение сохранено в элемент b[off] , следующий в b[off+1] , и так далее. Число чтения байтов, самое большее, равно len . Позвольте k быть числом байтов фактически чтение; эти байты будут сохранены в элементах b[off] через b[off+ k -1] , отъезд элементов b[off+ k ] через b[off+len-1] незатронутый. В каждом случае, элементах b[0] через b[off] и элементы b[off+len] через b[b.length-1] незатронуты. read(b, off, len) метод для класса InputStream просто вызывает метод read() неоднократно. Если первое такой призывать результаты IOException , то исключение возвращается из звонка read(b, off, len) метод. Если любой последующий звонок read() результаты в a IOException , исключение поймано и обработано, как будто это был конец файла; чтение байтов до той точки сохранено в b и число чтения байтов перед исключением произошло, возвращается. Реализация по умолчанию этого метода блоки до требуемого количества входных данных len был считан, конец файла обнаруживается, или исключение выдается. Подклассы поощряются обеспечить более эффективную реализацию этого метода.

пропустить

Перескакивает и отбрасывает n байты данных от этого входного потока. skip метод, для множества причин, может закончить тем, что перескочил через некоторое меньшее число байтов, возможно 0 . Это может следовать из любого из многих условий; достижение конца файла прежде n байты были пропущены, только одна возможность. Фактическое число пропущенных байтов возвращается. Если n отрицательно, никакие байты не пропускаются. skip метод этого класса создает байтовый массив и затем неоднократно не читает в него до n байты были считаны, или конец потока был достигнут. Подклассы поощряются обеспечить более эффективную реализацию этого метода. Например, реализация может зависеть от возможности искать.

доступный

Возвращает оценку числа байтов, которые могут быть считаны (или перескочиться) от этого входного потока, не блокируя следующим вызовом метода для этого входного потока. Следующий вызов мог бы быть тем же самым потоком или другим потоком. Единственное чтение или пропуск этого много байтов не будут блокировать, но могут считать или пропустить меньше байтов. Отметьте что в то время как некоторые реализации InputStream возвратит общее количество байтов в потоке, многие не будут. Это никогда не корректно, чтобы использовать возвращаемое значение этого метода, чтобы выделить буфер, предназначенный, чтобы содержать все данные в этом потоке. Реализация подкласса этого метода может хотеть бросать IOException если этот входной поток был закрыт, вызывая close() метод. available метод для класса InputStream всегда возвраты 0 . Этот метод должен быть переопределен подклассами.

близко

Завершения этот входной поток и выпуски любые системные ресурсы связались с потоком. close метод InputStream ничего не делает.

метка
public void mark(int readlimit)

Отмечает текущую позицию в этом входном потоке. Последующий звонок reset репозиции метода этот поток в последней отмеченной позиции так, чтобы последующие чтения, перечитанные те же самые байты. readlimit параметры говорят этому входному потоку признавать, что много байтов, которые будут считаны перед позицией метки, лишаются законной силы. Общий контракт mark это, если метод markSupported возвраты true , поток так или иначе помнит все чтение байтов после звонка mark и готов предоставлять те те же самые байты снова если и всякий раз, когда метод reset вызывается. Однако, поток не обязан помнить любые данные вообще если больше чем readlimit байты читаются из потока прежде reset вызывается. Отмечание закрытого потока не должно иметь никакого эффекта на поток. mark метод InputStream ничего не делает.

сброс
  • Если метод markSupported возвраты true , тогда:
    • Если метод mark не был вызван, так как поток создавался, или число байтов, считанных из потока с тех пор mark был последнее вызванный, больше чем параметр mark при той последней возможности, затем IOException мог бы быть брошен.
    • Если такой IOException не бросается, тогда поток сбрасывается к состоянию так, что все чтение байтов начиная с нового звонка mark (или начиная с запуска файла, если mark не был вызван), будет повторно предоставлен последующим вызывающим сторонам read метод, сопровождаемый любыми байтами, которые иначе были бы следующими входными данными со времени звонка reset .
    • Звонок reset может бросить IOException .
    • Если IOException не бросается, тогда поток сбрасывается к фиксированному состоянию, которое зависит от определенного типа входного потока и как это создавалось. Байты, которые будут предоставлены последующим вызывающим сторонам read метод зависит от определенного типа входного потока.
    markSupported
    public boolean markSupported()

    Тесты, если этот входной поток поддерживает mark и reset методы. Действительно ли mark и reset поддерживаются инвариантное свойство определенного входного потокового экземпляра. markSupported метод InputStream возвраты false .

    Платформа Java™
    Стандарт Эд. 7

    Представьте ошибку или функцию
    Для дальнейшей ссылки API и документации разработчика, см. Java Документация SE . Та документация содержит более подробные, предназначенные разработчиком описания, с концептуальными краткими обзорами, определениями сроков, обходных решений, и рабочих примеров кода.
    Авторское право © 1993, 2011, Oracle и/или его филиалы. Все права защищены.

    Чтение из InputStream с таймаутом в Java: решение

    Установка таймаута на InputStream возможна при его использовании в контексте Socket . Тогда вы можете применить метод setSoTimeout , чтобы установить таймаут. Если время таймаута будет превышено во время чтения, выбросится исключение SocketTimeoutException . «`java Socket socket = new Socket(«host», port); socket.setSoTimeout(5000); // Устанавливаем таймаут в 5 секунд.

    InputStream inputStream = socket.getInputStream(); // Читаем данные, и в случае превышения 5 секунд, будет выброшено SocketTimeoutException. «` Такой подход применим только для потоков, связанных с сокетами. В остальных ситуациях вам придется использовать NIO Java или реализовывать таймаут с помощью потоков.

    Специфика работы с System.in и особенности буферизации командной оболочки

    Учтите, что данные в System.in буферизуются командной оболочкой и становятся доступными для программы только после того, как пользователь нажмет Enter. Это может влиять на реализацию механизма таймаута через NIO, если вы используете System.in .

    Иерархия Executors и Callables для реализации таймаутов

    Реализация таймаута для InputStream предполагает инкапсуляцию процесса чтения в Callable и последующую передачу этого задания на выполнение ExecutorService . В данном контексте Callable выполняет роль надежного исполнителя, а ExecutorService – командира. «`java ExecutorService executor = Executors.newSingleThreadExecutor(); Future future = executor.submit(new Callable() < public String call() throws IOException < // Здесь производится чтение из InputStream >>);

    try < String result = future.get(5, TimeUnit.SECONDS); >catch (TimeoutException e) < // Бывает и так, что возникает исключение таймаута. В следующий раз все обязательно получится! >executor.shutdown(); // Очень важно не забыть остановить ExecutorService после его использования. « **Важно**: Обязательно останавливайте ExecutorService , используя метод shutdown()`.

    Работа с сетевыми операциями

    Использование Socket и HttpURLConnection

    Умение управлять сетевыми соединениями имеет критическое значение. Важно устанавливать таймауты для Sockets и HttpURLConnection , чтобы избегать бесполезного ожидания.

Добавить комментарий

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