Иерархия классов java.io.Writer

Эта статья является частью книги Java. Состояние языка и его перспективы (2022).

Диаграмма классов java.io.Writer . Используется в статье «Java 8 потоки ввода/вывода».

Иерархия классов java.io.Writer

Иерархия классов java.io.Reader

Эта статья является частью книги Java. Состояние языка и его перспективы (2022).

Диаграмма классов java.io.Reader. Используется в статье «Java 8 потоки ввода/вывода».

Иерархия классов java.io.Reader

Java 8 потоки ввода/вывода

Цикл статей «Учебник Java 8».

Следующая статья — «Java 8 сериализация».
Предыдущая статья — «Java 8 исключения».

Содержание

Введение

Потоки байт

Диаграмма классов, показывающая иерархию основных дочерних классов для класса java.io.InputStream

Диаграмма классов, показывающая иерархию основных дочерних классов для класса java.io.OutputStream

java.io.InputStream

java.io.OutputStream

java.io.FileInputStream и java.io.FileOutputStream

java.io.ByteArrayInputStream и java.io.ByteArrayOutputStream

java.io.FilterInputStream и java.io.FilterOutputStream

java.io.DataInputStream и java.io.DataOutputStream

java.io.BufferedInputStream и java.io.BufferedOutputStream

java.io.PipedInputStream и java.io.PipedOutputStream

java.io.ObjectInputStream и java.io.ObjectOutputStream

Потоки символов

Диаграмма классов, показывающая иерархию основных дочерних классов для java.io.Reader

Диаграмма классов, показывающая иерархию основных дочерних классов для java.io.Writer

java.util.Scanner и java.io.PrintStream

Введение

Поток ввода/вывода (I/O Stream) представляет собой источник данных или место их назначения. Потоки могут представлять собой абсолютно различные источники и места назначения: файлы на диска, устройства, сеть, другие программы, массивы в памяти т. д.

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

Независимо от внутреннего устройства потоки представляют собой одинаковую модель для программы. Поток представляет собой последовательность данных.

Потоки байт

Все классы, работающие с потоками байт, наследуются от абстрактных классов java.io.InputStream  или java.io.OutputStream.

Диаграмма классов, показывающая иерархию основных дочерних классов для класса java.io.InputStream

Иерархия классов java.io.InputStream

Диаграмма классов, показывающая иерархию основных дочерних классов для класса java.io.OutputStream

Иерархия классов java.io.OutputStream
Принцип работы с каждым из этих классов весьма схож. Важно знать методы java.io.InputStream  и java.io.OutputStream, поскольку они наследуются в каждом из этих классов.

java.io.InputStream

Абстрактный класс, являющийся базовым классом для всех классов, представляющий поток ввода.

Основные методы:

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

Закрывает поток и освобождает все ресурсы.

Помечает текущую позицию во входной строке. Работает только если markSupported()  возвращает true. Смысл этого метода в том, что поток каким-нибудь образом запоминает все считанные после вызова этого метода данные и может вернуть те же самые данные ещё раз после вызова метода reset(). Если после вызова метода mark(int readLimit)  из потока было прочитано больше readLimit  байт, то поток не обязан запоминать что бы то ни было.

Если метод markSupported()  возвращает true, то:

  • Если метод mark()  не был вызван ни разу, либо количество байт, которые были прочитаны из потока после вызова mark() , больше аргумента метода mark()  в последнем его вызове, то может броситься исключение IOException.
  • Если исключение IOException  не было брошено, то поток возвращается в такое состояние, что все вызовы методов read()  в дальнейшем будут возвращать те же данные, которые они возвращали с момента последнего вызова метода mark()  (либо с начала потока, если метод mark()  не был вызван ни разу).

Если метод markSupported()  возвращает false, то:

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

 

Возвращает true, если реализация InputStream  поддерживает методы mark() и reset().

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

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

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

Метод read(b)  у класса InputStream  имеет такой же эффект, что и read(b, 0, b.length), но дочерние классы могут переопределить его, если нужно.

Читает до len  байт из входного потока в массив байт. Пытается считать len  байт, но может считать и меньше. Количество реально считанных байт возвращается как int .

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

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

Первый байт считывается в b[off] , второй в b[off + 1]  и так далее.

Реализация этого метода в классе InputStream  просто вызывает метод read()  в цикле. Потомки могут переопределить это поведение на более оптимальное.

Пропускает n  следующих байт во входном потоке. Может пропустить меньшее количество байт по какой-нибудь причине. Возвращается реальное количество пропущенных байт.

java.io.OutputStream

Абстрактный класс, являющийся базовым классов для классов, реализующих выходной поток байт:

 

Основные методы:

Закрывает выходной поток и освобождает ресурсы.

Записывает все байты из буфера. Некоторые реализации выходного потока могут накапливать байты в буфере и лишь потом реально записывать их. Вызов этого методы принудительно записывает данные из буфера и очищает его.

Записывает байт в выходной поток.

Записывает b.length  байт из  указанного массива байт в выходной поток. Аналогично вызову write(b, 0, b.length).

Записывает len  байт из массива байт, начиная с off , в выходной поток. Реализация этого метода в OutputStream  вызывает в цикле метод write(int b). Дочерние классы могут переопределить его, дав более оптимальную реализацию.

java.io.FileInputStream и java.io.FileOutputStream

Предназначены для чтения и записи данных в файл и из файла. Пример использования:

В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы этих классов.

java.io.ByteArrayInputStream и java.io.ByteArrayOutputStream

Класс ByteArrayInputStream  позволяет создать входной поток, который будет считывать данные из массива байт. Класс ByteArrayOutputStream  позволяет записывать данные в поток, а по окончании получить записанные данные в виде массива байт с помощью метода toByteArray(). Принцип работы с этими классами такой же, как и с остальными наследниками java.io.InputStream  и java.io.OutputStream.

В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы и методы этих классов.

java.io.FilterInputStream и java.io.FilterOutputStream

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

В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы и методы этих классов.

java.io.DataInputStream и java.io.DataOutputStream

Классы DataInputStream  и DataOutputStream  позволяют платформонезависимо записывать в поток и считывать из потока примитивные типы языка Java. Класс DataInputStream  реализует интерфейс DataInput, который содержит методы для чтения примитивных типов, а класс DataOutputStream  реализует интерфейс DataOutput, который содержит методы для записи примитивных типов. Эти классы используют в качестве обёртки над другими потоками, например так:

Методы интерфейса DataInput  используют исключение java.io.EOFException для обозначения конца потока, в отличие от методов класса InputStream, которые возвращают -1.

В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы этих классов.

java.io.BufferedInputStream и java.io.BufferedOutputStream

Классы BufferedInputStream и BufferedOutputStream используют буфер, чтобы не нагружать систему операцией считывания и записи при каждом вызове методов write  и read.

В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы этих классов.

java.io.PipedInputStream и java.io.PipedOutputStream

Экземпляр класса PipedInputStream  должен быть связан с экземпляром класса PipedOutputStream  с помощью метода connect(PipedOutputStream src). С помощью PipedInputStream  считываются данные, которые в другом потоке записываются в PipedOutputStream.

В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы этих классов.

java.io.ObjectInputStream и java.io.ObjectOutputStream

Классы ObjectInputStream  и ObjectOutputStream  позволяют считывать объекты из потока и записывать объекты в поток, то есть используются для сериализации и десериализации объектов.

 

Потоки символов

Все классы потоков символов наследуются от java.io.Reader  или java.io.Writer. Как и у потоков байт есть два специализированных класса для файлового ввода/вывода: java.io.FileReader  и java.io.FileWriter. Работа с потоками символов аналогична работе с потоками классов.

Любой поток байт можно превратить в поток символов, обернув его в java.io.InputStreamReader  или в java.io.OutputStreamWriter  для потока вывода.

С помощью класса java.io.BufferedReader  можно считывать данные построчно, используя метод readLine() , который считает за конец строки символ '\n'  (LF), '\r'  (CR) или строку из двух символов "\r\n"  (CR LF).

Диаграмма классов, показывающая иерархию основных дочерних классов для java.io.Reader

Иерархия классов java.io.Reader

Диаграмма классов, показывающая иерархию основных дочерних классов для java.io.Writer

Иерархия классов java.io.Writer

java.util.Scanner и java.io.PrintStream

Класс PrintStream позволяет записывать в поток форматированные данные. Особенно важны его методы printf

Класс Scanner позволяет считывать из текста форматированные данные.

Работа с этими классами несколько отличается от работы с большинством классов, описанных в этой статье. Я не буду из здесь описывать. Когда-нибудь я, скорее всего, напишу отдельную статью по ним.

 

 

RandomAccessFile