GetInputStream: примеры (JAVA)
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()
(утечка дескриптора, возможны исчерпание ресурсов при множественных вызовах)
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() для чтения тела ошибки.
// В сервлете:
BufferedReader r = req.getReader();
ServletInputStream in = req.getInputStream();
java.lang.IllegalStateException: getInputStream() has already been called for this request
Одновременное использование текстового ридера и байтового потока запрещено.
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 напрямую в файл (без загружения в память)
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 для чтения сжатого ответа
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) без распаковки на диск
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+)
// Пример наброска: получение 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 для эффективной передачи данных
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 в асинхронном стиле
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. Обработка частично известных длин и потоковая валидация (пример чтения с контрольной суммой)
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
try (InputStream in = url.openStream()) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
in.transferTo(baos);
ByteBuffer buf = ByteBuffer.wrap(baos.toByteArray());
// buf готов для NIO операций
}
(ByteBuffer с данными готов к использованию)
Эти примеры демонстрируют гибкость работы с getInputStream и способы минимизировать потребление памяти и блокировки, а также интеграцию с современными API Java.