Что InputStream.available () делает в Java? - PullRequest
53 голосов
/ 12 сентября 2010

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

Документ говорит:

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

Доступный метод для класса InputStream всегда возвращает 0.

Что они означают под блокировкой ?Означает ли это только синхронизированный вызов?

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

Ответы [ 4 ]

40 голосов
/ 12 сентября 2010

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

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

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

27 голосов
/ 12 сентября 2010

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

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

Обратите внимание, что Java также имеет неблокирующие возможности ввода-вывода. Подробнее см. здесь

0 голосов
/ 25 января 2016

Один из возможно практических случаев использования 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 # доступны

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

JDK5 / InputStream # Availabe

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

0 голосов
/ 15 сентября 2013

Подумайте, пишете ли вы ПО ОЧЕНЬ ПЛОХО… и пишете операционную систему.

Эта операционная система, помимо прочего, принимает ввод с клавиатуры.

Итак, вы просите свою ОС пойти и получить ввод с клавиатуры, но в буфере нет нажатых клавиш. Ваша ОС в целом будет зависать, пока не получит ввод с клавиатуры.

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

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

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

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

...