+ [В чём заключается разница между IO и NIO?](#В-чём-заключается-разница-между-io-и-nio)
+ [Какие особенности NIO вы знаете?](#Какие-особенности-nio-вы-знаете)
+ [Что такое _«каналы»_?](#Что-такое-каналы)
+ [Какие существуют виды потоков ввода/вывода?](#Какие-существуют-виды-потоков-вводавывода)
+ [Назовите основные классы потоков ввода/вывода.](#Назовите-основные-классы-потоков-вводавывода)
+ [В каких пакетах расположены классы потоков ввода/вывода?](#В-каких-пакетах-расположены-классы-потоков-вводавывода)
+ [Какие подклассы класса `InputStream` вы знаете, для чего они предназначены?](#Какие-подклассы-класса-inputstream-вы-знаете-для-чего-они-предназначены)
+ [Для чего используется `PushbackInputStream`?](#Для-чего-используется-pushbackinputstream)
+ [Для чего используется `SequenceInputStream`?](#Для-чего-используется-sequenceinputstream)
+ [Какой класс позволяет читать данные из входного байтового потока в формате примитивных типов данных?](#Какой-класс-позволяет-читать-данные-из-входного-байтового-потока-в-формате-примитивных-типов-данных)
+ [Какие подклассы класса `OutputStream` вы знаете, для чего они предназначены?](#Какие-подклассы-класса-outputstream-вы-знаете-для-чего-они-предназначены)
+ [Какие подклассы класса `Reader` вы знаете, для чего они предназначены?](#Какие-подклассы-класса-reader-вы-знаете-для-чего-они-предназначены)
+ [Какие подклассы класса `Writer` вы знаете, для чего они предназначены?](#Какие-подклассы-класса-writer-вы-знаете-для-чего-они-предназначены)
+ [В чем отличие класса `PrintWriter` от `PrintStream`?](#В-чем-отличие-класса-printwriter-от-printstream)
+ [Чем отличаются и что общего у `InputStream`, `OutputStream`, `Reader`, `Writer`?](#Чем-отличаются-и-что-общего-у-inputstream-outputstream-reader-writer)
+ [Какие классы позволяют преобразовать байтовые потоки в символьные и обратно?](#Какие-классы-позволяют-преобразовать-байтовые-потоки-в-символьные-и-обратно)
+ [Какие классы позволяют ускорить чтение/запись за счет использования буфера?](#Какие-классы-позволяют-ускорить-чтениезапись-за-счет-использования-буфера)
+ [Какой класс предназначен для работы с элементами файловой системы?](#Какой-класс-предназначен-для-работы-с-элементами-файловой-системы)
+ [Какие методы класса `File` вы знаете?](#Какие-методы-класса-file-вы-знаете)
+ [Что вы знаете об интерфейсе `FileFilter`?](#Что-вы-знаете-об-интерфейсе-filefilter)
+ [Как выбрать все элементы определенного каталога по критерию (например, с определенным расширением)?](#Как-выбрать-все-элементы-определенного-каталога-по-критерию-например-с-определенным-расширением)
+ [Что вы знаете о `RandomAccessFile`?](#Что-вы-знаете-о-randomaccessfile)
+ [Какие режимы доступа к файлу есть у `RandomAccessFile`?](#Какие-режимы-доступа-к-файлу-есть-у-randomaccessfile)
+ [Какие классы поддерживают чтение и запись потоков в компрессированном формате?](#Какие-классы-поддерживают-чтение-и-запись-потоков-в-компрессированном-формате)
+ [Существует ли возможность перенаправить потоки стандартного ввода/вывода?](#Существует-ли-возможность-перенаправить-потоки-стандартного-вводавывода)
+ [Какой символ является разделителем при указании пути в файловой системе?](#Какой-символ-является-разделителем-при-указании-пути-в-файловой-системе)
+ [Что такое _«абсолютный путь»_ и _«относительный путь»_?](#Что-такое-абсолютный-путь-и-относительный-путь)
+ [Что такое _«символьная ссылка»_?](#Что-такое-символьная-ссылка)
+ Java IO (input-output) является потокоориентированным, а Java NIO (new/non-blocking io) – буфер-ориентированным. Потокоориентированный ввод/вывод подразумевает чтение/запись из потока/в поток одного или нескольких байт в единицу времени поочередно. Данная информация нигде не кэшируются. Таким образом, невозможно произвольно двигаться по потоку данных вперед или назад. В Java NIO данные сначала считываются в буфер, что дает больше гибкости при обработке данных.
+ Потоки ввода/вывода в Java IO являются блокирующими. Это значит, что когда в потоке выполнения вызывается `read()` или `write()` метод любого класса из пакета `java.io.*`, происходит блокировка до тех пор, пока данные не будут считаны или записаны. Поток выполнения в данный момент не может делать ничего другого. Неблокирующий режим Java NIO позволяет запрашивать считанные данные из канала (channel) и получать только то, что доступно на данный момент, или вообще ничего, если доступных данных пока нет. Вместо того, чтобы оставаться заблокированным пока данные не станут доступными для считывания, поток выполнения может заняться чем-то другим. Тоже самое справедливо и для неблокирующего вывода. Поток выполнения может запросить запись в канал некоторых данных, но не дожидаться при этом пока они не будут полностью записаны.
+ В Java NIO имеются селекторы, которые позволяют одному потоку выполнения мониторить несколько каналов ввода. Т.е. существует возможность зарегистрировать несколько каналов с селектором, а потом использовать один поток выполнения для обслуживания каналов, имеющих доступные для обработки данные, или для выбора каналов, готовых для записи.
+ __Каналы и селекторы__: NIO поддерживает различные типы каналов. Канал является абстракцией объектов более низкого уровня файловой системы (например, отображенные в памяти файлы и блокировки файлов), что позволяет передавать данные с более высокой скоростью. Каналы не блокируются и поэтому Java предоставляет еще такие инструменты, как селектор, который позволяет выбрать готовый канал для передачи данных, и сокет, который является инструментом для блокировки.
+ __Буферы__: имеет буферизация для всех классов-обёрток примитивов (кроме Boolean). Появился абстрактный класс Buffer, который предоставляет такие операции, как clear, flip, mark и т.д. Его подклассы предоставляют методы для получения и установки данных.
+ __Кодировки__: появились кодеры и декодеры для отображения байт и символов Unicode.
Каналы (channels) – это логические (не физические) порталы, абстракции объектов более низкого уровня файловой системы (например, отображенные в памяти файлы и блокировки файлов), через которые осуществляется ввод/вывод данных, а буферы являются источниками или приёмниками этих переданных данных. При организации вывода, данные, которые необходимо отправить, помещаются в буфер, который затем передается в канал. При вводе, данные из канала помещаются в заранее предоставленный буфер.
Каналы напоминают трубопроводы, по которым эффективно транспортируются данные между буферами байтов и сущностями по ту сторону каналов. Каналы – это шлюзы, которые позволяют получить доступ к сервисам ввода/вывода операционной системы с минимальными накладными расходами, а буферы – внутренние конечные точки этих шлюзов, используемые для передачи и приема данных.
+ `ByteArrayInputStream` позволяет использовать буфер в памяти (массив байтов) в качестве источника данных для входного потока;
+ `DataInputStream` - входной поток для байтовых данных, включающий методы для чтения стандартных типов данных Java;
+ `FileInputStream` - входной поток для чтения информации из файла;
+ `FilterInputStream` - абстрактный класс, предоставляющий интерфейс для классов-надстроек, которые добавляют к существующим потокам полезные свойства;
+ `ObjectInputStream` - входной поток для объектов;
+ `StringBufferInputStream` превращает строку (`String`) во входной поток данных `InputStream`;
+ `PipedInputStream` реализует понятие входного канала;
+ `PrintStream` - выходной поток, включающий методы `print()` и `println()`;
+ PushbackInputStream - разновидность буферизации, обеспечивающая чтение байта с последующим его возвратом в поток, позволяет «заглянуть» во входной поток и увидеть, что оттуда поступит в следующий момент, не извлекая информации.
+ `SequenceInputStream` используется для слияния двух или более потоков `InputStream` в единый.
Разновидность буферизации, обеспечивающая чтение байта с последующим его возвратом в поток. Класс `PushbackInputStream` представляет механизм «заглянуть» во входной поток и увидеть, что оттуда поступит в следующий момент, не извлекая информации.
Класс `SequenceInputStream` позволяет сливать вместе несколько экземпляров класса `InputStream`. Конструктор принимает в качестве аргумента либо пару объектов класса `InputStream`, либо интерфейс `Enumeration`.
Во время работы класс выполняет запросы на чтение из первого объекта класса `InputStream` и до конца, а затем переключается на второй. При использовании интерфейса работа продолжится по всем объектам класса `InputStream`. По достижении конца, связанный с ним поток закрывается. Закрытие потока, созданного объектом класса `SequenceInputStream`, приводит к закрытию всех открытых потоков.
Класс `DataInputStream` представляет поток ввода и предназначен для записи данных примитивных типов, таких, как `int`, `double` и т.д. Для каждого примитивного типа определен свой метод для считывания:
+ `boolean readBoolean()`: считывает из потока булевое однобайтовое значение
+ `byte readByte()`: считывает из потока 1 байт
+ `char readChar()`: считывает из потока значение `char`
+ `double readDouble()`: считывает из потока 8-байтовое значение `double`
+ `float readFloat()`: считывает из потока 4-байтовое значение `float`
+ `int readInt()`: считывает из потока целочисленное значение `int`
+ `long readLong()`: считывает из потока значение `long`
+ `short readShort()`: считывает значение `short`
+ `String readUTF()`: считывает из потока строку в кодировке UTF-8
Прежде всего, в классе `PrintWriter` применен усовершенствованный способ работы с символами Unicode и другой механизм буферизации вывода: в классе PrintStream буфер вывода сбрасывался всякий раз, когда вызывался метод `print()` или `println()`, а при использовании класса `PrintWriter` существует возможность отказаться от автоматического сброса буферов, выполняя его явным образом при помощи метода `flush()`.
Кроме того, методы класса `PrintWriter` никогда не создают исключений. Для проверки ошибок необходимо явно вызвать метод `checkError()`.
`File` работает непосредственно с файлами и каталогами. Данный класс позволяет создавать новые элементы и получать информацию существующих: размер, права доступа, время и дату создания, путь к родительскому каталогу.
Интерфейс `FileFilter` применяется для проверки, попадает ли объект `File` под некоторое условие. Этот интерфейс содержит единственный метод `boolean accept(File pathName)`. Этот метод необходимо переопределить и реализовать. Например:
Метод `File.listFiles()` возвращает массив объектов `File`, содержащихся в каталоге. Метод может принимать в качестве параметра объект класса, реализующего `FileFilter`. Это позволяет включить список только те элементы, для которые метода `accept` возвращает `true` (критерием может быть длина имени файла или его расширение).
Класс `java.io.RandomAccessFile` обеспечивает чтение и запись данных в произвольном месте файла. Он не является частью иерархии `InputStream` или `OutputStream`. Это полностью отдельный класс, имеющий свои собственные (в большинстве своем _native_) методы. Объяснением этого может быть то, что `RandomAccessFile` имеет во многом отличающееся поведение по сравнению с остальными классами ввода/вывода так как позволяет, в пределах файла, перемещаться вперед и назад.
`RandomAccessFile` имеет такие специфические методы как:
+ `getFilePointer()` для определения текущего местоположения в файле;
+ `seek()` для перемещения на новую позицию в файле;
+ `length()` для выяснения размера файла;
+ `setLength()` для установки размера файла;
+ `skipBytes()` для того, чтобы попытаться пропустить определённое число байт;
+ `getChannel()` для работы с уникальным файловым каналом, ассоциированным с заданным файлом;
+ методы для выполнения обычного и форматированного вывода из файла (`read()`, `readInt()`, `readLine()`, `readUTF()` и т.п.);
+ методы для обычной или форматированной записи в файл с прямым доступом (`write()`, `writeBoolean()`, `writeByte()` и т.п.).
Так же следует отметить, что конструкторы `RandomAccessFile` требуют второй аргумент, указывающий необходимый режим доступа к файлу - только чтение (`"r"`), чтение и запись (`"rw"`) или иную их разновидность.
+ `"r"` открывает файл только для чтения. Запуск любых методов записи данных приведет к выбросу исключения `IOException`.
+ `"rw"` открывает файл для чтения и записи. Если файл еще не создан, то осуществляется попытка создать его.
+ `"rws"` открывает файл для чтения и записи подобно `"rw"`, но требует от системы при каждом изменении содержимого файла или метаданных синхронно записывать эти изменения на физический носитель.
+ `"rwd"` открывает файл для чтения и записи подобно `"rws"`, но требует от системы синхронно записывать изменения на физический носитель только при каждом изменении содержимого файла. Если изменяются метаданные, синхронная запись не требуется.
__Абсолютный (полный) путь__ — это путь, который указывает на одно и то же место в файловой системе, вне зависимости от текущей рабочей директории или других обстоятельств. Полный путь всегда начинается с корневого каталога.
__Относительный путь__ представляет собой путь по отношению к текущему рабочему каталогу пользователя или активного приложения.
__Символьная (символическая) ссылка__ (также «симлинк», Symbolic link) — специальный файл в файловой системе, в котором, вместо пользовательских данных, содержится путь к файлу, который должен быть открыт при попытке обратиться к данной ссылке (файлу). Целью ссылки может быть любой объект: например, другая ссылка, файл, каталог или даже несуществующий файл (в последнем случае, при попытке открыть его, должно выдаваться сообщение об отсутствии файла).
Символьные ссылки используются для более удобной организации структуры файлов на компьютере, так как:
+ позволяют для одного файла или каталога иметь несколько имён и различных атрибутов;
+ свободны от некоторых ограничений, присущих жёстким ссылкам (последние действуют только в пределах одной файловой системы (одного раздела) и не могут ссылаться на каталоги).