Какие знаешь базовые реализации InputStream?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Реализации InputStream в Java
InputStream это абстрактный базовый класс для работы с байтовыми потоками. Есть множество реализаций для разных сценариев.
1. FileInputStream - чтение из файла
Самая базовая реализация для чтения файлов с диска:
public class FileInputExample {
public void readFile(String path) throws IOException {
FileInputStream fis = new FileInputStream(path);
try {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
System.out.write(buffer, 0, bytesRead);
}
} finally {
fis.close(); // Важно: закрывать ресурсы
}
}
// Правильный способ с try-with-resources
public void readFileCorrectly(String path) throws IOException {
try (FileInputStream fis = new FileInputStream(path)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
System.out.write(buffer, 0, bytesRead);
}
}
}
}
2. ByteArrayInputStream - работа с памятью
Для работы с массивом байтов, как если бы это был поток:
public class ByteArrayExample {
public void parseByteArray() throws IOException {
byte[] data = "Hello World".getBytes();
try (ByteArrayInputStream bais = new ByteArrayInputStream(data)) {
byte[] buffer = new byte[5];
int bytesRead;
while ((bytesRead = bais.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, bytesRead));
}
}
}
// Полезно при тестировании
public String processInputStream(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
int b;
while ((b = is.read()) != -1) {
sb.append((char) b);
}
return sb.toString();
}
// Тест с ByteArrayInputStream
public void testProcessing() throws IOException {
String input = "test data";
InputStream is = new ByteArrayInputStream(input.getBytes());
String result = processInputStream(is);
assert "test data".equals(result);
}
}
3. FilterInputStream - обёртка для добавления функциональности
Абстрактный класс для создания цепочки потоков:
public class FilterExample {
// BufferedInputStream - буферизация
public void readWithBuffer(String path) throws IOException {
try (FileInputStream fis = new FileInputStream(path);
BufferedInputStream bis = new BufferedInputStream(fis)) {
int b;
while ((b = bis.read()) != -1) {
System.out.write(b);
}
}
}
// DataInputStream - чтение примитивных типов
public void readData(String path) throws IOException {
try (FileInputStream fis = new FileInputStream(path);
DataInputStream dis = new DataInputStream(fis)) {
int intValue = dis.readInt(); // 4 байта
double doubleValue = dis.readDouble(); // 8 байт
String stringValue = dis.readUTF(); // UTF-8 строка
System.out.println("Int: " + intValue);
System.out.println("Double: " + doubleValue);
System.out.println("String: " + stringValue);
}
}
// PushbackInputStream - возврат байт в поток
public void readWithPushback() throws IOException {
try (FileInputStream fis = new FileInputStream("test.txt");
PushbackInputStream pis = new PushbackInputStream(fis)) {
int b = pis.read();
if (b == 'X') {
pis.unread(b); // Вернуть байт обратно
}
}
}
// GZIPInputStream - распаковка
public void readCompressed(String path) throws IOException {
try (FileInputStream fis = new FileInputStream(path);
GZIPInputStream gis = new GZIPInputStream(fis)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = gis.read(buffer)) != -1) {
System.out.write(buffer, 0, bytesRead);
}
}
}
}
4. PipedInputStream - для inter-thread передачи данных
Два потока общаются через пайп:
public class PipedStreamExample {
public void pipedCommunication() throws IOException {
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
// Поток-писатель
new Thread(() -> {
try {
String message = "Hello from another thread";
pos.write(message.getBytes());
pos.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
// Поток-читатель (основной поток)
try (pis) {
byte[] buffer = new byte[1024];
int bytesRead = pis.read(buffer);
String received = new String(buffer, 0, bytesRead);
System.out.println("Received: " + received);
}
}
}
5. StringBufferInputStream (deprecated) и альтернативы
Уже устаревший класс, нужно использовать современные способы:
public class StringStreamExample {
// Старый способ (deprecated)
@Deprecated
public void oldWay(String data) throws IOException {
// StringBufferInputStream stream = new StringBufferInputStream(data);
}
// Правильный способ
public void modernWay(String data) throws IOException {
try (InputStream is = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8))) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
System.out.write(buffer, 0, bytesRead);
}
}
}
}
6. SequenceInputStream - объединение потоков
Объединить несколько потоков в один:
public class SequenceExample {
public void mergeStreams() throws IOException {
try (FileInputStream fis1 = new FileInputStream("file1.txt");
FileInputStream fis2 = new FileInputStream("file2.txt");
FileInputStream fis3 = new FileInputStream("file3.txt")) {
SequenceInputStream sis = new SequenceInputStream(
fis1,
new SequenceInputStream(fis2, fis3)
);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = sis.read(buffer)) != -1) {
System.out.write(buffer, 0, bytesRead);
}
}
}
// С использованием Collections
public void mergeMultipleStreams(List<FileInputStream> streams) throws IOException {
Enumeration<InputStream> enumeration = Collections.enumeration(streams);
try (SequenceInputStream sis = new SequenceInputStream(enumeration)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = sis.read(buffer)) != -1) {
System.out.write(buffer, 0, bytesRead);
}
}
}
}
7. Пользовательская реализация InputStream
Иногда нужна специальная реализация для своего источника данных:
public class CustomInputStream extends InputStream {
private int value = 65; // 'A'
private int count = 0;
private static final int MAX = 26;
@Override
public int read() throws IOException {
if (count >= MAX) {
return -1; // EOF
}
return value++;
}
@Override
public void close() throws IOException {
System.out.println("Closed");
}
}
// Использование
public class CustomStreamDemo {
public void demo() throws IOException {
try (CustomInputStream cis = new CustomInputStream()) {
int b;
while ((b = cis.read()) != -1) {
System.out.print((char) b);
}
}
// Выведет: ABCDEFGHIJKLMNOPQRSTUVWXYZ
}
}
8. ObjectInputStream - десериализация объектов
Для чтения сериализованных Java объектов:
public class ObjectStreamExample {
public void deserializeObject(String path) throws IOException, ClassNotFoundException {
try (FileInputStream fis = new FileInputStream(path);
ObjectInputStream ois = new ObjectInputStream(fis)) {
MySerializable obj = (MySerializable) ois.readObject();
System.out.println("Deserialized: " + obj);
}
}
}
public class MySerializable implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
// getters, setters, constructor
}
Сравнение реализаций
| Класс | Назначение | Буферизация | Примечание |
|---|---|---|---|
| FileInputStream | Файлы | Нет | Базовый, медленный без BufferedInputStream |
| ByteArrayInputStream | Память | Встроена | Полезна при тестировании |
| BufferedInputStream | Обёртка | Да | Сильно улучшает производительность |
| DataInputStream | Примитивы | Зависит | Чтение типизированных данных |
| PipedInputStream | Inter-thread | Встроена | Для передачи между потоками |
| SequenceInputStream | Объединение | Нет | Мерж нескольких потоков |
| GZIPInputStream | Распаковка | Зависит | Для сжатых данных |
| ObjectInputStream | Десериализация | Встроена | Для Java объектов |
Лучшие практики
public class BestPractices {
// Всегда используй try-with-resources
public void readFile(String path) throws IOException {
try (InputStream is = new FileInputStream(path)) {
// работа с потоком
}
}
// Используй буферизацию для файлов
public void readFileEfficiently(String path) throws IOException {
try (InputStream is = new BufferedInputStream(
new FileInputStream(path), 8192)) {
// работа с потоком
}
}
// Правильный размер буфера
public void readWithProperBuffer() throws IOException {
try (InputStream is = new FileInputStream("file.txt")) {
byte[] buffer = new byte[8192]; // 8KB - оптимальный размер
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
// обработка данных
}
}
}
}
Выбор правильной реализации InputStream влияет на производительность и удобство работы с данными. Для production кода всегда используй буферизацию и try-with-resources для автоматического закрытия ресурсов.