Закриття потоків. Класи ByteArrayInputStream та ByteArrayOutputStream

Прокрутити вниз


Закриття потоків є важливим етапом при роботі з введенням-виведенням у Java, оскільки воно забезпечує звільнення ресурсів, що використовуються потоком, таких як дескриптори файлів. Якщо потоки не закривати, це може призвести до витоку ресурсів і вичерпання системних обмежень на відкриті файли або мережеві з’єднання.

Закриття потоків

У Java для закриття потоку використовується метод close(), який реалізовано в інтерфейсі Closeable (успадковується класами потоків). Починаючи з Java 7, з’явилася зручна конструкція try-with-resources, яка автоматично закриває потік після завершення роботи або після того, як було викинуто виняток.

Приклад використання try-with-resources:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Main {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream(“input.txt”);
FileOutputStream fos = new FileOutputStream(“output.txt”)) {

int byteData;
while ((byteData = fis.read()) != -1) {
fos.write(byteData);
}
} catch (IOException e) {
e.printStackTrace();
}
// Потоки автоматично закриваються після завершення блоку try
}
}

У цьому прикладі, навіть якщо виникає виняток, потоки fis і fos автоматично закриються завдяки конструкції try-with-resources.

Класи ByteArrayInputStream і ByteArrayOutputStream

Ці класи використовуються для роботи з байтовими масивами замість файлів чи інших зовнішніх джерел/потоків даних.

1. ByteArrayInputStream

ByteArrayInputStream дозволяє читати байти з масиву як із потоку. Це корисно, коли потрібно працювати з даними, що вже зберігаються в пам’яті, як із звичайного потоку.

Основні методи:

  • int read() — читає наступний байт з потоку.
  • int read(byte[] b, int off, int len) — читає до len байтів у масив b, починаючи з позиції off.
  • void reset() — скидає внутрішній вказівник на початок потоку.

Приклад використання ByteArrayInputStream:

import java.io.ByteArrayInputStream;
import java.io.IOException;

public class Main {
public static void main(String[] args) {
byte[] data = “Hello, World!”.getBytes();
try (ByteArrayInputStream bais = new ByteArrayInputStream(data)) {
int byteData;
while ((byteData = bais.read()) != -1) {
System.out.print((char) byteData); // Виводимо символи
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

2. ByteArrayOutputStream

ByteArrayOutputStream дозволяє записувати байти у внутрішній буфер, а потім отримати ці дані як масив байтів або рядок. Це зручно для створення тимчасових буферів даних у пам’яті.

Основні методи:

  • void write(int b) — записує один байт.
  • void write(byte[] b, int off, int len) — записує масив байтів.
  • byte[] toByteArray() — повертає масив байтів, записаних у потік.
  • String toString() — повертає записані байти у вигляді рядка.

Приклад використання ByteArrayOutputStream:

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class Main {
public static void main(String[] args) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
String message = “Hello, ByteArrayOutputStream!”;
baos.write(message.getBytes());

// Отримуємо записані дані у вигляді масиву байтів
byte[] byteArray = baos.toByteArray();
System.out.println(new String(byteArray)); // Виводимо дані у вигляді рядка
} catch (IOException e) {
e.printStackTrace();
}
}
}

Основні моменти:

  • ByteArrayInputStream читає дані з масиву байтів.
  • ByteArrayOutputStream записує дані у внутрішній масив байтів.
  • Ці класи часто використовуються для тимчасового зберігання даних у пам’яті перед їх подальшою обробкою або передачею.

Закриття потоківКласи ByteArrayInputStream та ByteArrayOutputStream