Подтвердить что ты не робот

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

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

Док говорит:

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

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

Ответ 3

Считайте, если вы пишете ПО ОЧЕНЬ БЕДЛИ.. и вы пишете операционную систему.

Эта операционная система также использует клавиатуру.

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

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

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

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

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

Ответ 4

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

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

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

JDK5/InputStream # availabe

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