webprogr.ru Новости

RSS

{{toodo.preview}}

...
{{toodo.name}}

{{toodo.preview}}

далее..

{{toodo.preview}}

{{toodo.name}}

{{toodo.preview}}

смотреть..

toodo.name

{{toodo.preview}}

{{toodo.name}}

{{toodo.preview}}

перейти...

{{toodo.preview}}

...
{{toodo.name}}

{{toodo.preview}}

далее..

{{toodo.preview}}

{{toodo.name}}

{{toodo.preview}}

смотреть..

toodo.name

{{toodo.preview}}

{{toodo.name}}

{{toodo.preview}}

перейти...


Последние новости

Введение в потоки ввода/вывода

Поток данных (Stream) – абстракция для последовательного ввода/вывода информации. Поток можно представить как канал, по которому байты идут от источника данных к приемнику.

Назначение потоков: с помощью потоков Java-программа обменивается данными с внешними ресурсами – файлами на диске, консолью, сетевыми сокетами и др.

Классы потоков: базовые классы для работы с потоками находятся в пакетах java.io (стандартные блокирующие I/O) и java.nio (новая I/O, поддержка неблокирующих каналов и буферов).

Основные виды потоков: по направлению передачи данных различают входные (Input) и выходные (Output) потоки; по типу данных – байтовые (InputStream/OutputStream) для двоичной информации и символьные (Reader/Writer) для текста; по организации – буферизированные (BufferedInputStream, BufferedReader и др.) и небуферизированные (низкоуровневые потоки без буфера).

Автоматическое закрытие: современные потоки поддерживают автоматическое освобождение ресурсов через конструкцию try-with-resources (требует интерфейса AutoCloseable), что упрощает корректное закрытие файлов и сокетов.

Пояснение:
В Java операции ввода и вывода реализованы через понятие потока данных. Под потоком понимается последовательность байтов, которая передается из одной точки в другую. Когда программа читает файл или получает данные из сети, она делает это через входной поток; когда она записывает данные на диск или отправляет по сети – использует выходной поток. Таким образом, поток ввода обеспечивает чтение данных в программу, а поток вывода – запись данных из программы во внешний ресурс.
 
Все классы, задействованные во вводе-выводе (I/O), сгруппированы в пакетах java.io и java.nio. Пакет java.io содержит классические блокирующие потоки, которые работают в режиме последовательного чтения/записи. Пакет java.nio (New I/O) был добавлен для более эффективного и неблокирующего ввода-вывода: он вводит такие концепции, как каналы (Channel) и буферы (Buffer), позволяющие, например, обрабатывать файлы и сокеты без создания потока на каждое соединение. В современной Java разработчики могут использовать API java.nio для масштабируемого ввода-вывода, однако базовые принципы работы со stream-ами остаются теми же.
 
Категории потоков. Потоки классифицируются по нескольким критериям. Во-первых, по направлению передачи данных:

Входной поток (Input stream) – предназначен для чтения данных из внешнего источника (например, файла, сокета или клавиатуры) в приложение.


Выходной поток (Output stream) – служит для вывода данных из приложения во внешний приемник (файл, сетевой соединение, консоль и т.д.).

Во-вторых, по природе обрабатываемых данных:

Байтовые потоки оперируют сырыми байтами. К этой категории относятся классы, наследующие InputStream и OutputStream. Байтовые потоки подходят для чтения и записи двоичных файлов (изображения, видео, любые несимвольные данные) либо текстовых файлов в неизвестной/нестандартной кодировке. Они не выполняют никаких преобразований данных – читают и пишут байты как есть.


Символьные потоки (наследники Reader и Writer) работают с текстовыми данными. Такие потоки автоматически преобразуют байты в символы и обратно в соответствии с заданной кодировкой (по умолчанию используется системная или UTF-8). Символьные потоки удобны для чтения и записи текстовых файлов, так как избавляют программиста от ручной обработки кодировки символов.

В-третьих, по способу организации буферизации:

Небуферизированные потоки осуществляют чтение/запись данных по мере запроса каждого байта или символа. Примеры: FileInputStream, FileOutputStream, FileReader, FileWriter. Каждый вызов метода чтения из такого потока может приводить к непосредственной операции с источником (например, обращение к диску), что относительно медленно.


Буферизированные потоки используют внутренний промежуточный буфер. При чтении они заранее считывают крупный блок данных во внутреннюю память, а затем выдают программе по запросу уже из памяти. При записи, наоборот, они накапливают выходные данные во внутреннем буфере и периодически записывают большим блоком. Благодаря этому число реальных обращений к диску или сети сокращается, что значительно повышает производительность ввода-вывода. В Java к буферизированным относятся, например, BufferedInputStream/BufferedOutputStream для байтовых данных и BufferedReader/BufferedWriter для символов. Как правило, имеет смысл оборачивать любой интенсивно используемый файловый поток в соответствующий Buffered-класс для эффективной работы.

Автоматическое закрытие потоков. Правильное управление ресурсами — важная часть работы с I/O. Открытые файловые дескрипторы и сетевые сокеты занимают системные ресурсы, поэтому после окончания операций их нужно закрыть, вызвав метод close(). Ранее это делалось вручную в блоке finally. Однако начиная с Java 7 появилась конструкция try-with-resources, которая значительно упростила этот шаблон. Если открыть поток внутри круглых скобок try (...), то JVM гарантированно закроет его в конце блока, даже если произошло исключение. Например:
try (FileInputStream fin = new FileInputStream("data.bin")) {
    // чтение из файла
}  // при выходе из try поток fin закроется автоматически
Для использования try-with-resources класс потока должен реализовывать интерфейс AutoCloseable (все стандартные потоки это делают). В современной практике Java рекомендуется всегда использовать try-with-resources для работы с файлами и другими ресурсами ввода-вывода – это делает код более надежным и облегчит его чтение.
 

Рейтинг@Mail.ru