GetInputStream: примеры (JAVA)

Примеры работы метода getInputStream в Java
Раздел: Ввод-вывод (I/O) сетевой (NIO/Сокеты)
getInputStream: InputStream

Общее описание метода getInputStream

В Java термин getInputStream чаще всего относится к методам, возвращающим объект java.io.InputStream или его подклассы и позволяющим читать данные из ресурса. Типичные реализации встречаются в следующих API: java.net.URLConnection#getInputStream(), java.net.HttpURLConnection#getInputStream(), javax.servlet.ServletRequest#getInputStream(), java.util.zip.ZipFile#getInputStream(ZipEntry) и некоторых обёртках библиотек. Метод обычно не принимает аргументов (за исключением случаев, как у ZipFile), возвращает InputStream и при ошибках выбрасывает исключения ввода-вывода.

Когда используется

  • Для чтения удалённого HTTP/FTP/файлового ресурса через URLConnection.
  • Для получения тела HTTP-ответа при работе с HttpURLConnection.
  • Для чтения тела запроса на сервере в сервлетах (ServletInputStream).
  • Для получения содержимого конкретного ZIP-элемента через ZipFile.

Аргументы и возвращаемые значения

  • URLConnection.getInputStream(): нет аргументов. Возвращает InputStream. Может автоматически открыть соединение. Выбрасывает IOException при проблемах с сетью или если ресурс не найден.
  • HttpURLConnection.getInputStream(): нет аргументов. Возвращает InputStream. Если код ответа сервера указывает на ошибку (обычно >=400), метод выбрасывает IOException; в этом случае можно использовать getErrorStream() для чтения тела ошибки.
  • ServletRequest.getInputStream(): нет аргументов. Возвращает ServletInputStream. Может выбросить IllegalStateException, если уже был вызван getReader() для той же заявки, и IOException при проблемах ввода-вывода.
  • ZipFile.getInputStream(ZipEntry entry): аргумент - объект ZipEntry. Возвращает InputStream для чтения содержимого записи ZIP. Выбрасывает IOException при ошибках или если запись отсутствует.

Дополнительные замечания

  • Возвращаемый InputStream обычно блокирующий и требует явного закрытия во избежание утечек ресурсов; предпочтителен try-with-resources.
  • Метод не занимается декодированием текста (кодировкой); чтение текста требует конвертации через InputStreamReader с указанием нужной кодировки.
  • Поведение при ошибках и порядок открытия соединения зависят от конкретной реализации (URLConnection vs HttpURLConnection vs Servlet API).

Короткие примеры использования

1. Чтение по URL с URLConnection (или URL.openStream)

// Пример: чтение небольшого текста с URL
URL url = new URL("https://example.com/");
try (InputStream in = url.openStream();
     BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
    String line = r.readLine();
    System.out.println(line);
}
<!doctype html>... (первая строка HTML страницы example.com)

2. HttpURLConnection: успешный ответ и ошибка

URL u = new URL("https://httpbin.org/status/200");
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setRequestMethod("GET");
try (InputStream in = conn.getInputStream()) {
    System.out.println("OK, длина доступных байт: " + in.available());
} catch (IOException e) {
    InputStream err = conn.getErrorStream();
    System.out.println("Ошибка, тело ошибки: " + (err != null));
}
OK, длина доступных байт: 0

3. HttpURLConnection при коде 404 (пример с getErrorStream)

URL u2 = new URL("https://httpbin.org/status/404");
HttpURLConnection c2 = (HttpURLConnection) u2.openConnection();
try (InputStream in = c2.getInputStream()) {
    // в большинстве реализаций сюда не попадут при 404
} catch (IOException ex) {
    try (InputStream err = c2.getErrorStream()) {
        System.out.println("Ошибка сервера, errorStream доступен: " + (err != null));
    }
}
Ошибка сервера, errorStream доступен: true

4. ServletRequest.getInputStream (чтение тела POST)

// В методе doPost(HttpServletRequest req, HttpServletResponse resp)
ServletInputStream sin = req.getInputStream();
String body = new BufferedReader(new InputStreamReader(sin, StandardCharsets.UTF_8))
        .lines().collect(Collectors.joining("\n"));
resp.getWriter().write("Получено: " + body);
Получено: поле1=значение&поле2=значение

5. ZipFile.getInputStream

try (ZipFile zf = new ZipFile("archive.zip")) {
    ZipEntry e = zf.getEntry("data.txt");
    try (InputStream in = zf.getInputStream(e)) {
        System.out.println(new String(in.readAllBytes(), StandardCharsets.UTF_8));
    }
}
Содержимое data.txt из архива

Похожие методы в Java и их особенности

  • URL.openStream() - краткая обёртка для URLConnection#getInputStream(). Удобна для быстрого чтения ресурсов.
  • URLConnection.getErrorStream() - специфична для HttpURLConnection: возвращает поток тела ответа при ошибочном коде (обычно при исключении из getInputStream).
  • URLConnection.getContent() - возвращает объект контента, может вернуть InputStream или другой тип в зависимости от Content-Type; менее предсказуема для поточного чтения.
  • Files.newInputStream(Path) и new FileInputStream(File) - для локальной файловой системы; предпочитаются при работе с файлами вместо URLConnection.
  • ServletRequest.getReader() - возвращает текстовый BufferedReader; используется вместо getInputStream при необходимости читать текст непосредственно. Совместимость: нельзя вызывать оба метода для одного запроса.
  • ResultSet.getBinaryStream() - получение бинарных данных из базы данных; функционально сопоставим с getInputStream для BLOB.

Выбор между этими методами зависит от источника данных: для сетевых ресурсов - URLConnection/HttpURLConnection, для файлов - Files/FileInputStream, для сервлетов - ServletInputStream/Reader, для ZIP - ZipFile.

Аналоги в других языках и краткие примеры

PHP

// file_get_contents
$txt = file_get_contents('https://example.com');
var_dump(substr($txt, 0, 50));

// fopen + fread
$h = fopen('https://example.com', 'r');
echo fgets($h, 1024);
fclose($h);
string(50) "<!doctype html>..."  
"<!doctype html>..."

JavaScript (в браузере/Node.js)

// fetch в браузере
fetch('https://example.com').then(r => r.text()).then(t => console.log(t.slice(0,50)));

// ReadableStream в браузере
fetch('https://example.com').then(r => {
  const reader = r.body.getReader();
  return reader.read();
}).then(console.log);
"<!doctype html>..."  
{ value: Uint8Array(...), done: false }

Python

import urllib.request
with urllib.request.urlopen('https://example.com') as r:
    data = r.read(100)
print(data[:50])

# Файловый аналог
with open('file.txt','rb') as f:
    print(f.read(50))
b'<!doctype html>...'  
b'первые 50 байт файла'

C#

// HttpWebRequest / HttpWebResponse
var req = (HttpWebRequest)WebRequest.Create("https://example.com");
using var resp = (HttpWebResponse)req.GetResponse();
using var s = resp.GetResponseStream();
byte[] buf = new byte[100];
int n = s.Read(buf,0,buf.Length);
Console.WriteLine(n);

// HttpClient
var client = new HttpClient();
using var stream = await client.GetStreamAsync("https://example.com");
100  // прочитано байт
(Stream доступен)

Go

resp, _ := http.Get("https://example.com")
defer resp.Body.Close()
b := make([]byte, 100)
n, _ := resp.Body.Read(b)
fmt.Println(n, string(b[:n]))
100 <!doctype html>...

Kotlin

// Использование Java API
val url = URL("https://example.com")
url.openStream().buffered().use { println(it.readBytes().size) }
длина в байтах

SQL (BLOB)

// JDBC
ResultSet rs = stmt.executeQuery("select filedata from files where id=1");
if (rs.next()) {
  try (InputStream in = rs.getBinaryStream(1)) {
    byte[] data = in.readAllBytes();
  }
}
(байты BLOB)

Lua

local f = io.open('file.bin','rb')
local s = f:read(100)
f:close()
print(#s)
100

Отличия от Java

  • Во многих языках (PHP, Python, C#, Go) чтение сети и файлов происходит через унифицированные функции, не всегда требующие явного открытия соединения отдельным объектом как в URLConnection.
  • В Java 11+ появился современный HttpClient с более гибкими способами получения тела (в том числе как InputStream), что делает переключение с HttpURLConnection предпочтительным для новых приложений.
  • В SQL/DB API обычно возвращается поток для BLOB-данных, функционально аналогичный getInputStream.

Типичные ошибки при использовании getInputStream

  • Не закрытый поток
  • InputStream in = url.openStream();
    byte[] data = in.readAllBytes();
    // пропущен in.close()
    (утечка дескриптора, возможны исчерпание ресурсов при множественных вызовах)
  • Использование getInputStream при ошибочном HTTP-ответе
  • HttpURLConnection c = (HttpURLConnection) u.openConnection();
    try (InputStream in = c.getInputStream()) { ... }
    catch (IOException e) { /* ожидался контент в теле ошибки */ }
    java.io.IOException: Server returned HTTP response code: 404 for URL: ...

    При ошибке следует проверить код ответа и вызвать getErrorStream() для чтения тела ошибки.

  • IllegalStateException в сервлетах
  • // В сервлете:
    BufferedReader r = req.getReader();
    ServletInputStream in = req.getInputStream();
    java.lang.IllegalStateException: getInputStream() has already been called for this request

    Одновременное использование текстового ридера и байтового потока запрещено.

  • NullPointerException или отсутствие записи в ZipFile
  • ZipEntry e = zf.getEntry("no.txt");
    InputStream in = zf.getInputStream(e);
    java.lang.NullPointerException или IOException: Entry not found
  • Блокировка чтения и ожидание данных
  • Чтение из сетевого InputStream блокирует поток, пока данные не станут доступны или соединение не завершится. Для GUI/серверных приложений предпочтительна обработка в выделенных потоках или использование неблокирующего API.

Изменения и эволюция в недавних версиях

  • Java 9+: добавлены удобные методы ввода-вывода, такие как InputStream.transferTo(OutputStream) и readAllBytes(), упрощающие работу с InputStream.
  • Java 11: появился модульный и поддерживаемый java.net.http.HttpClient, предоставляющий современную альтернативу HttpURLConnection. HttpClient предлагает синхронные и асинхронные способы получения тела, включая BodyHandlers.ofInputStream() (позволяет получить InputStream для ответа).
  • В Servlet API поведение ServletInputStream было дополнено возможностью неблокирующего чтения и асинхронной обработки в более новых версиях сервлета.
  • Сам метод getInputStream как правило не помечался устаревшим; изменения касаются сопутствующих API и удобных утилит для безопасного закрытия и передачи потоков.

Расширенные варианты и редкие сценарии

1. Потоковая запись ответа HTTP напрямую в файл (без загружения в память)

Пример java
URL url = new URL("https://speed.hetzner.de/100MB.bin");
try (InputStream in = url.openStream();
     OutputStream out = Files.newOutputStream(Paths.get("download.bin"))) {
    in.transferTo(out); // Java 9+
}
System.out.println("Скачано в download.bin");
Скачано в download.bin

2. Использование GZIPInputStream для чтения сжатого ответа

Пример java
HttpURLConnection conn = (HttpURLConnection) new URL("https://example.com/data.gz").openConnection();
try (InputStream raw = conn.getInputStream();
     GZIPInputStream gin = new GZIPInputStream(raw)) {
    byte[] data = gin.readAllBytes();
    System.out.println("Декомпрессировано: " + data.length);
}
Декомпрессировано: 10240

3. Чтение ZIP внутри ZIP (nested archive) без распаковки на диск

Пример java
try (ZipFile outer = new ZipFile("outer.zip")) {
    ZipEntry innerZip = outer.getEntry("inner.zip");
    try (InputStream innerStream = outer.getInputStream(innerZip);
         ZipInputStream zin = new ZipInputStream(innerStream)) {
        ZipEntry e;
        while ((e = zin.getNextEntry()) != null) {
            System.out.println("Entry: " + e.getName());
            // чтение e из zin
            zin.closeEntry();
        }
    }
}
Entry: file1.txt
Entry: dir/file2.dat

4. Неблокирующее чтение в сервлетах (Servlet 3.1+)

Пример java
// Пример наброска: получение ServletInputStream и регистрация ReadListener
ServletInputStream in = req.getInputStream();
in.setReadListener(new ReadListener() {
    public void onDataAvailable() throws IOException { byte[] buf = new byte[4096]; while (in.isReady() && !in.isFinished()) { int n = in.read(buf); /* обработка */ } }
    public void onAllDataRead() throws IOException { /* завершение */ }
    public void onError(final Throwable t) { /* обработка ошибки */ }
});
(асинхронная обработка тела запроса без блокировки потоков сервлета)

5. Использование Channels для эффективной передачи данных

Пример java
try (InputStream in = url.openStream();
     ReadableByteChannel rbc = Channels.newChannel(in);
     FileOutputStream fos = new FileOutputStream("out.bin")) {
    fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
}
(файл out.bin создан, данные записаны без промежуточного массива)

6. HttpClient (Java 11) с InputStream в асинхронном стиле

Пример java
HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder(URI.create("https://example.com/large"))
        .GET().build();
HttpResponse resp = client.send(req, HttpResponse.BodyHandlers.ofInputStream());
try (InputStream in = resp.body()) {
    in.transferTo(Files.newOutputStream(Paths.get("large.bin")));
}
(ответ записан в large.bin)

7. Обработка частично известных длин и потоковая валидация (пример чтения с контрольной суммой)

Пример java
try (InputStream in = url.openStream()) {
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    byte[] buf = new byte[8192];
    int r;
    while ((r = in.read(buf)) != -1) {
        md.update(buf,0,r);
    }
    System.out.println("SHA-256: " + DatatypeConverter.printHexBinary(md.digest()));
}
SHA-256: A1B2C3... (контрольная сумма)

8. Преобразование InputStream в поток байтов NIO ByteBuffer

Пример java
try (InputStream in = url.openStream()) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    in.transferTo(baos);
    ByteBuffer buf = ByteBuffer.wrap(baos.toByteArray());
    // buf готов для NIO операций
}
(ByteBuffer с данными готов к использованию)

Эти примеры демонстрируют гибкость работы с getInputStream и способы минимизировать потребление памяти и блокировки, а также интеграцию с современными API Java.

джава getInputStream function comments

En
GetInputStream Returns an input stream for this socket