2010-09-12 4 views
41

Что делает InputStream.available() в Java? Я прочитал документацию, но я все еще не могу разобраться.Что делает InputStream.available() в Java?

Док говорит:

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

Имеющийся метод класса InputStream всегда возвращает 0.

Что они означают блокирующим? Это просто означает синхронный вызов?

И самое главное, какова цель метода available()?

+1

Существует очень мало полезного использования доступных(). Один из них предназначен для чтения из System in. – EJP

ответ

24

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

Так зачем использовать available()? Таким образом, вы можете определить количество байтов для чтения или определить, собираетесь ли вы блокировать.

Обратите внимание, что Java также имеет неблокирующие возможности ввода-вывода. См. here для получения более подробной информации.

+0

Я наткнулся на этот вопрос, и теперь я задаюсь вопросом, могу ли я использовать доступные() для решения моей собственной проблемы, не прибегая к NIO. Мой вопрос: http://stackoverflow.com/questions/3867042/one-thread-per-client-doable –

+6

Этот ответ неверен. Блокирующий вызов блокируется, пока есть * нет * доступных данных. Если вы попросите четырех, а их три, вы получите три. – EJP

+0

Теперь это правильно, спасибо Брайан. – EJP

30

В InputStreams, read() вызовы называются вызовами «блокировки». Это означает, что, если во время вызова метода данные отсутствуют, метод будет ожидать получения данных.

Метод available() указывает, сколько байтов может быть прочитано до тех пор, пока вызов read() не заблокирует поток выполнения вашей программы. На большинстве входных потоков все вызовы read() блокируются, поэтому по умолчанию доступны 0.

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

+7

BufferedInputStream.available() сообщает вам, сколько байтов может быть прочитано без блокировки. Это * сумма * количества байтов уже в буфере и результат avaiable() вложенного входного потока. Обратите внимание также, что available() всегда возвращает ноль для сокета SSL. – EJP

+0

То, что я не совсем понял, это то, что означает * использование * знания этого. Я действительно, не могу понять, почему мне это нужно, т. Е. Я не вижу, где и когда в приложении mu я мог бы найти его для использования. Конечно, довольно очевидно, что я незнаю, но это для моего * недостатка опыта. –

+0

Как я сказал выше, очень мало полезных применений. Вы должны знать, что имеете дело с потоком, который предоставит ненулевой ответ, а затем вы должны использовать результат. – EJP

-2

Рассмотрите, если вы пишете программное обеспечение ОЧЕНЬ ПЛОХО .. и вы пишете операционную систему.

Эта операционная система вводит клавиатуру среди других вещей.

Итак, вы попросите свою ОС пойти и получить ввод с клавиатуры, но нет никаких нажатых клавиш и ни одного в буфере. Ваша целая ОС будет ХАГОВАТЬ МЕРТВОЙ, пока она не получит ввод с клавиатуры.

Контрастность этого с «взглядом вперед», вы спрашиваете, имеет ли КБ какие-либо символы перед выполнением вызова. Вы получаете ответ НЕТ, поэтому ваша ОС затем идет и делает что-то еще.

Это ПОЧЕМУ вы должны заботиться, теперь, если вы затем умножаете это на любую другую потенциально блокирующую задачу, вы можете понять, почему «смотреть вперед» имеет решающее значение.

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

Это также подчеркивает бессмыслицу «очень мало полезных применений».

+0

Нет, нет. Я не говорю о написании программного обеспечения очень плохо; Я не говорил о написании операционных систем; Я не говорил о записи на интерфейс дисковода: 'available()' не помогает вам писать. Я говорил о 'InputStream.available()' в *** Java, ***, который был многопоточным в последний раз, когда я смотрел. Один действительный пример, который вы приводите здесь, совпадает с исключением, о котором я говорил: чтение с клавиатуры. – EJP

-2

Один из возможно-практический Использование available() использует его для выбора разумной длины буфера.

static final int LEN = 4096; 

long copy(InputStream in, OutputStream out) throws IOException { 
    int count = 0L; 
    int avl = in.available(); 
    if (avl == 0) { 
     // 0 returned without IOException? possibly mean eof? 
     return 0L; 
    } 
    //byte[] buf = new byte[avl == 0 ? LEN : Math.min(avl, LEN)]; 
    byte[] buf = new byte[Math.min(avl, LEN)]; 
    for (int len; (len = in.read(buf)) != -1; count+= len) { 
     out.write(buf, 0, len); 
    } 
    return count; 
} 

В документе говорится,

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

И

Подкласс реализация этого метода может выбрать, чтобы бросить IOException, если этот входной поток был закрыт, вызывая метод close().

UPDATE

Я уже знаю, идея не рекомендуется. Я знал, что риск даже до того, как документ JDK предупредил. (Я когда-то пытался выделяемой буфер из available из нескольких ГБ размером FileInputStream.)

JDK8/InputStream#available

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

JDK5/InputStream#availabe

Но, в программировании, то должны не never или always wrong код. Вот что я верю.

+1

Нет, нет, и нет. Прочтите javadoc. «Неправильно использовать возвращаемое значение этого метода для выделения буфера, предназначенного для хранения всех данных в этом потоке». – Grod

+0

@ Gordon Я уже прочитал javadoc. И поэтому я сказал * возможно-практический * и использовал 'Math # min'. –

+1

Ключевые слова "НИКОГДА". Не имеет значения, считаете ли вы, что это «возможно-практично». Не используйте его таким образом. Скажем, вы читаете 16777216 байт (16 миров). 'available()' может возвращать 4 в момент выделения вашего буфера. Теперь вы выделили 4-байтовый буфер и будете запускать этот цикл 4194304 раз. Когда javadoc говорит «никогда», это означает, что НЕ ДЕЛАЙТЕ ЭТО. – Grod

Смежные вопросы