Эта статья является частью книги Java. Состояние языка и его перспективы (2022).
Диаграмма классов java.io.Writer . Используется в статье «Java 8 потоки ввода/вывода».
Эта статья является частью книги Java. Состояние языка и его перспективы (2022).
Диаграмма классов java.io.Writer . Используется в статье «Java 8 потоки ввода/вывода».
Эта статья является частью книги Java. Состояние языка и его перспективы (2022).
Диаграмма классов java.io.Reader. Используется в статье «Java 8 потоки ввода/вывода».
Цикл статей «Учебник Java 8».
Следующая статья — «Java 8 сериализация».
Предыдущая статья — «Java 8 исключения».
— Диаграмма классов, показывающая иерархию основных дочерних классов для класса 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.OutputStream, поскольку они наследуются в каждом из этих классов.
Абстрактный класс, являющийся базовым классом для всех классов, представляющий поток ввода.
1 2 |
public int available() throws IOException |
Возвращает количество байт, которое может быть прочитано из потока без блокировки. Некоторые реализации
InputStream возвращают полное количество байт в потоке, но не все. Не стоит использовать этот метод для определения размера буфера, который будет хранить все данные из потока.
1 2 |
public void close() throws IOException |
Закрывает поток и освобождает все ресурсы.
1 |
public void mark(int readlimit) |
Помечает текущую позицию во входной строке. Работает только если
markSupported() возвращает
true. Смысл этого метода в том, что поток каким-нибудь образом запоминает все считанные после вызова этого метода данные и может вернуть те же самые данные ещё раз после вызова метода
reset(). Если после вызова метода
mark(int readLimit) из потока было прочитано больше
readLimit байт, то поток не обязан запоминать что бы то ни было.
1 2 |
public void reset() throws IOException |
Если метод markSupported() возвращает true, то:
Если метод markSupported() возвращает false, то:
1 |
public boolean markSupported() |
Возвращает
true, если реализация
InputStream поддерживает методы mark() и reset().
1 2 |
public abstract int read() throws IOException |
Считывает один байт из потока. Возвращает его в
int, содержащем значение от 0 до 255. Возвращает -1, если достигли конца потока. Блокирует выполнение текущего потока программы до тех пор, пока не появятся входные данные, не достигнется конец потока, либо бросится исключение.
1 2 |
public int read(byte[] b) throws IOException |
Считывает некоторое количество байт из входного потока и сохраняет его в массив байт b. Возвращает количество считанных байт, которое может быть меньше длины массива. Метод блокирует выполнение текущего потока программы до тех пор, пока не появятся входные данные, не достигнется конец потока, либо бросится исключение.
Если длина массива b равна нулю, то байты не считываются и возвращается 0, в противном случае происходит попытка считать хотя бы один байт. Если достигнут конец потока, то возвращается -1.
Метод
read(b) у класса
InputStream имеет такой же эффект, что и
read(b, 0, b.length), но дочерние классы могут переопределить его, если нужно.
1 2 3 4 |
public int read(byte[] b, int off, int len) throws IOException |
Читает до len байт из входного потока в массив байт. Пытается считать len байт, но может считать и меньше. Количество реально считанных байт возвращается как int .
Этот метод блокирует выполнение текущего потока программы до тех пор, пока не появятся данные, не будет достигнут конец потока, либо возникнет исключение.
Если len равен нулю, то байты не считываются, и возвращается 0. В противном случае происходит попытка считать хотя бы один байт. Если никаких байт нет, так как был достигнут конец потока, то возвращается -1, иначе хотя бы один байт считывается и сохраняется в b.
Первый байт считывается в b[off] , второй в b[off + 1] и так далее.
Реализация этого метода в классе
InputStream просто вызывает метод
read() в цикле. Потомки могут переопределить это поведение на более оптимальное.
1 2 |
public long skip(long n) throws IOException |
Пропускает n следующих байт во входном потоке. Может пропустить меньшее количество байт по какой-нибудь причине. Возвращается реальное количество пропущенных байт.
Абстрактный класс, являющийся базовым классов для классов, реализующих выходной поток байт:
Основные методы:
1 2 |
public void close() throws IOException |
Закрывает выходной поток и освобождает ресурсы.
1 2 |
public void flush() throws IOException |
Записывает все байты из буфера. Некоторые реализации выходного потока могут накапливать байты в буфере и лишь потом реально записывать их. Вызов этого методы принудительно записывает данные из буфера и очищает его.
1 2 |
public abstract void write(int b) throws IOException |
Записывает байт в выходной поток.
1 2 |
public void write(byte[] b) throws IOException |
Записывает
b.length байт из указанного массива байт в выходной поток. Аналогично вызову
write(b, 0, b.length).
1 2 3 4 |
public void write(byte[] b, int off, int len) throws IOException |
Записывает len байт из массива байт, начиная с off , в выходной поток. Реализация этого метода в OutputStream вызывает в цикле метод write(int b). Дочерние классы могут переопределить его, дав более оптимальную реализацию.
Предназначены для чтения и записи данных в файл и из файла. Пример использования:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import java.io.InputStream; import java.io.OutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; class Main { public static void main(String[] args) { try (InputStream is = new FileInputStream("input.txt"); OutputStream os = new FileOutputStream("output.txt")) { int bytesReaded; final int BUFFER_SIZE = 10_000; byte[] buff = new byte[BUFFER_SIZE]; while ((bytesReaded = is.read(buff)) != -1) { os.write(buff, 0, bytesReaded); } } catch (IOException ioex) { ioex.printStackTrace(); } } } |
В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы этих классов.
Класс ByteArrayInputStream позволяет создать входной поток, который будет считывать данные из массива байт. Класс ByteArrayOutputStream позволяет записывать данные в поток, а по окончании получить записанные данные в виде массива байт с помощью метода toByteArray(). Принцип работы с этими классами такой же, как и с остальными наследниками java.io.InputStream и java.io.OutputStream.
В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы и методы этих классов.
Базовые классы для потоков, которые содержат внутри себя другой поток и производят некую трансформацию записываемых и считываемых данных.
В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы и методы этих классов.
Классы DataInputStream и DataOutputStream позволяют платформонезависимо записывать в поток и считывать из потока примитивные типы языка Java. Класс DataInputStream реализует интерфейс DataInput, который содержит методы для чтения примитивных типов, а класс DataOutputStream реализует интерфейс DataOutput, который содержит методы для записи примитивных типов. Эти классы используют в качестве обёртки над другими потоками, например так:
1 |
DataInputStream dis = new DataInputStream(new FileInputStream("myfile.data")); |
Методы интерфейса DataInput используют исключение java.io.EOFException для обозначения конца потока, в отличие от методов класса InputStream, которые возвращают -1.
В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы этих классов.
Классы BufferedInputStream и BufferedOutputStream используют буфер, чтобы не нагружать систему операцией считывания и записи при каждом вызове методов write и read.
В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы этих классов.
Экземпляр класса PipedInputStream должен быть связан с экземпляром класса PipedOutputStream с помощью метода connect(PipedOutputStream src). С помощью PipedInputStream считываются данные, которые в другом потоке записываются в PipedOutputStream.
В диаграмме наследников InputStream и диаграмме наследников OutputStream показаны конструкторы этих классов.
Классы ObjectInputStream и ObjectOutputStream позволяют считывать объекты из потока и записывать объекты в поток, то есть используются для сериализации и десериализации объектов.
Все классы потоков символов наследуются от java.io.Reader или java.io.Writer. Как и у потоков байт есть два специализированных класса для файлового ввода/вывода: java.io.FileReader и java.io.FileWriter. Работа с потоками символов аналогична работе с потоками классов.
Любой поток байт можно превратить в поток символов, обернув его в java.io.InputStreamReader или в java.io.OutputStreamWriter для потока вывода.
1 2 3 |
try (Reader reader = new InputStreamReader(new ByteArrayInputStream(byteArray), "windows-1251")) { // ... some code } |
С помощью класса java.io.BufferedReader можно считывать данные построчно, используя метод readLine() , который считает за конец строки символ '\n' (LF), '\r' (CR) или строку из двух символов "\r\n" (CR LF).
Класс PrintStream позволяет записывать в поток форматированные данные. Особенно важны его методы printf
Класс Scanner позволяет считывать из текста форматированные данные.
Работа с этими классами несколько отличается от работы с большинством классов, описанных в этой статье. Я не буду из здесь описывать. Когда-нибудь я, скорее всего, напишу отдельную статью по ним.
RandomAccessFile