← Назад к вопросам

Какие знаешь базовые реализации InputStream?

2.3 Middle🔥 131 комментариев
#Stream API и функциональное программирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Реализации 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ПримитивыЗависитЧтение типизированных данных
PipedInputStreamInter-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 для автоматического закрытия ресурсов.

Какие знаешь базовые реализации InputStream? | PrepBro