Что InputStream.available() делает в Java?

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

Док говорит:

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

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

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

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

4 ответа

Решение

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

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

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

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

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

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

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

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

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

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

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

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

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

Одно из возможных практических применений 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() метод.

ОБНОВИТЬ

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

JDK8 / InputStream # доступен

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

JDK5 / InputStream # Availabe

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

Другие вопросы по тегам