Глядя на InputStream из исходного кода JDK

Java задняя часть исходный код API
Глядя на InputStream из исходного кода JDK

Обзор

JDK предоставляет нам множество практичных потоков ввода xxxInputStream, а InputStream — это абстракция всех потоков ввода байтов. Включая ByteArrayInputStream, FilterInputStream, BufferedInputStream, DataInputStream и PushbackInputStream и т. д.

структура наследования

--java.lang.Object
  --java.io.InputStream

определение класса

public abstract class InputStream implements Closeable

InputStream определяется как общедоступный и абстрактный класс, реализующий интерфейс Closeable.

Интерфейс Closeable указывает, что InputStream может быть закрыт.Интерфейс определяется следующим образом:

public interface Closeable extends AutoCloseable {
    public void close() throws IOException;
}

главный атрибут

private static final int MAX_SKIP_BUFFER_SIZE = 2048;

private static final int DEFAULT_BUFFER_SIZE = 8192;

private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
  • MAX_SKIP_BUFFER_SIZE указывает максимальное количество байтов, которое входной поток может пропустить за раз.
  • DEFAULT_BUFFER_SIZE Размер буфера по умолчанию.
  • MAX_BUFFER_SIZE представляет собой максимальный размер буферного массива, для которого задано значение Integer.MAX_VALUE — 8. При этом также учитывается размер, который может поддерживать JVM. Превышение этого значения вызовет ошибку OutOfMemoryError.

основной метод

метод чтения

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

  1. Есть читаемые байты.
  2. Обнаружен конец входного потока.
  3. Сбросить исключение.

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


    public abstract int read() throws IOException;

    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }
    public int read(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        int c = read();
        if (c == -1) {
            return -1;
        }
        b[off] = (byte)c;

        int i = 1;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException ee) {
        }
        return i;
    }

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

метод readAllBytes

Метод считывает все оставшиеся байты из входного потока, блокируя процесс до тех пор, пока не будут прочитаны все оставшиеся байты, не будет достигнут конец потока или не возникнет исключение.

Логика заключается в использовании цикла for для встраивания цикла while. Цикл while постоянно вызывает метод чтения, чтобы попытаться заполнить массив байтов длиной DEFAULT_BUFFER_SIZE. После его заполнения емкость массива необходимо удвоить, а затем исходный байтовый массив копируется в новый.В массиве, а затем продолжают чтение через цикл while, пока не будет достигнут конец, цикл for выпрыгивает, и в итоге возвращаются все прочитанные байтовые массивы.

    public byte[] readAllBytes() throws IOException {
        byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
        int capacity = buf.length;
        int nread = 0;
        int n;
        for (;;) {
            while ((n = read(buf, nread, capacity - nread)) > 0)
                nread += n;
            if (n < 0)
                break;
            if (capacity <= MAX_BUFFER_SIZE - capacity) {
                capacity = capacity << 1;
            } else {
                if (capacity == MAX_BUFFER_SIZE)
                    throw new OutOfMemoryError("Required array size too large");
                capacity = MAX_BUFFER_SIZE;
            }
            buf = Arrays.copyOf(buf, capacity);
        }
        return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
    }

метод readNBytes

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

    public int readNBytes(byte[] b, int off, int len) throws IOException {
        Objects.requireNonNull(b);
        if (off < 0 || len < 0 || len > b.length - off)
            throw new IndexOutOfBoundsException();
        int n = 0;
        while (n < len) {
            int count = read(b, off + n, len - n);
            if (count < 0)
                break;
            n += count;
        }
        return n;
    }

доступные методы

Возвращает оставшееся количество байтов, которые могут быть прочитаны без блокировки из входного потока. При вызове read количество прочитанных байтов обычно меньше этого значения. Некоторые классы подреализации InputStream возвращают общее количество оставшихся байтов потока с помощью этого метода Числа, но некоторые нет, поэтому будьте осторожны при их использовании.

Здесь абстрактный класс напрямую возвращает 0, а метод переопределяется в подклассе.

public int available() throws IOException {
        return 0;
    }

метод пропуска

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

Рассмотрим логику ниже.Максимальная длина пропуска не может превышать MAX_SKIP_BUFFER_SIZE, а метод чтения вызывается с циклом while.Если возвращается -1, то есть достигнут конец, цикл будет выскочить . Можно видеть, что skipBuffer на самом деле бесполезен, просто позвольте ему быть GCed напрямую и, наконец, верните количество фактически пропущенных байтов.

    public long skip(long n) throws IOException {

        long remaining = n;
        int nr;

        if (n <= 0) {
            return 0;
        }

        int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
        byte[] skipBuffer = new byte[size];
        while (remaining > 0) {
            nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
            if (nr < 0) {
                break;
            }
            remaining -= nr;
        }

        return n - remaining;
    }

метод закрытия

Этот метод используется для закрытия входного потока и освобождения связанных ресурсов.

public void close() throws IOException {}

метод TransferTo

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

Основная логика заключается в использовании цикла while для непрерывного вызова метода чтения для чтения байтов, а затем вызова метода записи выходного потока для записи до тех пор, пока чтение не вернет -1, то есть не будет достигнут конец. Наконец, возвращает количество переданных байтов.

    public long transferTo(OutputStream out) throws IOException {
        Objects.requireNonNull(out, "out");
        long transferred = 0;
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        int read;
        while ((read = this.read(buffer, 0, DEFAULT_BUFFER_SIZE)) >= 0) {
            out.write(buffer, 0, read);
            transferred += read;
        }
        return transferred;
    }

метод markSupported

Поддерживать ли операции пометки и сброса, возвращать false прямо здесь, а подклассы переопределяют этот метод в соответствии с реальной ситуацией.

    public boolean markSupported() {
        return false;
    }

метод маркировки

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

Вы можете видеть, что метод маркировки InputStream ничего не делает и реализован в подклассе.

public synchronized void mark(int readlimit) {}

метод сброса

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

    public synchronized void reset() throws IOException {
        throw new IOException("mark/reset not supported");
    }

Ниже приведенырекламироватьа такжеСвязанное Чтение

========Время рекламы========

Моя новая книга «Анализ дизайна ядра Tomcat» продана на Jingdong, нуждающиеся друзья могут обратиться кitem.JD.com/12185360.Контракт…Зарезервировать. Спасибо друзья.

Зачем писать «Анализ проектирования ядра Tomcat»

=========================

Связанное чтение:

Объект с точки зрения исходного кода JDK
Долго с точки зрения исходного кода JDK
Целое число с точки зрения исходного кода JDK
Достаточно ли изменчив, чтобы гарантировать синхронизацию данных?
Разговор об основных типах данных Java
Оптимизация одновременных блокировок с точки зрения исходного кода JDK
Блокировка и пробуждение потоков с точки зрения исходного кода JDK
С точки зрения исходного кода JDK тайм-аут параллельной конкуренции
Прерывание параллельных потоков Java с точки зрения исходного кода JDK
Справедливость параллелизма Java с точки зрения исходного кода JDK
Как обеспечить атомарность параллелизма Java с точки зрения исходного кода JDK
Глядя на Writer из исходного кода JDK
Глядя на хук выключения из исходного кода JDK
Байт с точки зрения исходного кода JDK
Логическое значение с точки зрения исходного кода JDK
Кратко с точки зрения исходного кода JDK

Добро пожаловать, чтобы следовать:

这里写图片描述
напишите сюда описание фото

这里写图片描述
напишите сюда описание фото