JavaRush /Курсы /Java Syntax Pro /Работа с сетью

Работа с сетью

Java Syntax Pro
15 уровень , 6 лекция
Открыта

1. Класс URL

Работу с потоками ввода-вывода мы уже изучили, работу с файлами изучили, что же изучить дальше? А как насчет работы с сетью и интернетом? Звучит многообещающе, не так ли?

В Java работать с интернетом не сложнее, чем работать с файлами. Ну разве что совсем чуть-чуть.

Для работы с ресурсами в интернете в Java есть специальный класс — URL. Он простой, как табуретка, в чем вы сейчас и убедитесь.

Получение странички из интернета

Как вы думаете, сколько строк кода нужно написать, чтобы скачать какой-нибудь текстовый файл из интернета и отобразить его содержимое на экране? 10? 100? 1000? А может быть, 5?

Код Примечание
URL url = new URL("https://javarush.com");
InputStream input = url.openStream();
byte[] buffer = input.readAllBytes();
String str = new String(buffer);
System.out.println(str);
Создает объект URL с путем к странице
Получает InputStream у интернет-объекта
Читает все байты и возвращает массив байт
Преобразуем массив в строку
Выводим строку на экран

На экране отобразится содержимое HTML-файла:

Вывод на экран
<!DOCTYPE html><html lang="ru" class="light"><head>
    <meta charset="utf-8″>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1″>
    ...

Сравнение работы File и URL

URL — это такой аналог File или Path, только Path хранит путь к ресурсу в файловой системе, а URL — путь к ресурсу в интернете.

Вся магия происходит, когда мы за один вызов метода openStream() получаем сразу объект типа InputStream. Это же стандартный объект, и мы его уже изучили вдоль и поперек. Все становится очевидно уже после получения объекта типа InputStream. Ведь как вычитать из него данные, мы уже знаем.

Сравните: отличаются только две первые строчки, и то немного. Вот оно, преимущество стандартизации и работы с цепочками потоков данных:

Работа с интернетом Работа с файлом
URL url = new URL("https://javarush.com");
InputStream input = url.openStream(); 
byte[] buffer = input.readAllBytes();
String str = new String(buffer);
System.out.println(str);
File file = new File("c:\\readme.txt");
InputStream input = new FileInputStream(file);

byte[] buffer = input.readAllBytes();
String str = new String(buffer);
System.out.println(str);


2. Класс URLConnection

Кроме простого чтения данных из интернета, мы еще можем и загружать туда данные. Загрузка данных — это куда более сложный процесс, чем считывание. Вам понадобится на несколько методов больше. Пример:

Код Примечание
URL url = new URL("https://javarush.com");
URLConnection connection = url.openConnection();

// получили поток для отправки данных
OutputStream output = connection.getOutputStream();
output.write(1); // отправляем данные

// получили поток для чтения данных
InputStream input = connection.getInputStream();
int data = input.read(); // читаем данные
Создаем объект URL с путем к странице
Создаем двустороннее соединение


Получаем поток вывода
Выводим в него данные


Получаем поток ввода
Читаем из него данные

Обратите внимание, что тут мы больше не вызываем метод url.openStream(). Вместо этого мы идем по более длинному пути:

  • Сначала мы устанавливаем стабильное двустороннее соединение с помощью метода URLConnection openConnection()
  • Затем получаем поток для отправки данных с помощью метода connection.getOutputStream() и отправляем данные серверу
  • Затем получаем поток для чтения данных с помощью метода connection.getInputStream() и начинаем читать из него данные.

Контроль ресурсов

Строго говоря, мы должны все потоки обернуть в try-with-resources для безопасной работы. А еще не помешало бы обернуть голые InputStream и OutputStream во что-нибудь более удобное. Например, в PrintStream и BufferedReader.

Если мы все это сделаем, наш код будет выглядеть как-то так:

URL url = new URL("https://javarush.com");
URLConnection connection = url.openConnection(); // отправляем данные
try (OutputStream output = connection.getOutputStream();
   PrintStream sender = new PrintStream(output))
{
   sender.println("Привет");
}

// читаем данные
try(InputStream input = connection.getInputStream();
   BufferedReader reader = new BufferedReader(new InputStreamReader(input)))
{
   while (reader.ready())
      System.out.println(reader.readLine());
}

3. Примеры работы с сетью

А давай-ка мы что-нибудь загрузим из интернета. И не просто загрузим, а сохраним на диск.

Например, давайте напишем программу, которая сохраняет на диск картинку с главной страницы Google.

В принципе ничего сложного. В самой простой интерпретации этот код будет выглядеть так:

Сохранение файла на диск
String image = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
URL url = new URL(image);
InputStream input = url.openStream();

Path path = Path.of("c:\\GoogleLogo.png");
Files.copy(input, path);

С помощью трех первых строк мы получаем поток данных от интернет-ресурса — от картинки.

В четвертой строке мы создаем имя файла, в который будем сохранять картинку. Имя может быть любым, однако расширение файла должно совпадать с расширением картинки в интернете. Так локальные программы просмотра картинок будут правильно ее открывать.

Ну и наконец, последняя строка — это один из методов copy класса Files. У класса Files их несколько. Этот метод, который мы использовали, принимает в качестве первого параметра источник данных — байтовый поток (InputStream), а в качестве второго параметра — имя файла, куда нужно записывать данные.

Теоретически, если бы URL картинки был коротким, этот код вообще можно было бы записать в одну строку:

Копирование данных из потока в файл
Files.copy(
   new URL("https://www.google.com/logo.png").openStream(),
   Path.of("c:\\GoogleLogo.png")
);

Писать так, конечно же, не нужно, однако этот пример демонстрирует, насколько удобные и мощные в Java потоки ввода-вывода.



Комментарии (304)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Grigoryvvv Уровень 17 Expert
29 июня 2026
29.06.2026 / 16 уровень
Real User Уровень 40
14 апреля 2026
Какое-то странное богом забытое апи. Очень сомневаюсь что кто-то когда-то будет использовать его в таком виде. ( начиналось еще вроде нормально, закончилось дичью ) 90 процентов java разработчиков будут использовать http клиенты , и нормально параметризировать запросы телом, хедерами, типами запросов и пр. , а не отправлять рандомные байты, в общем применимость 0 , зачем нужно не ясно, жирный минус Надеюсь это смотрят мейнтейнеры курса
Anonymous #3519817 Уровень 18
26 апреля 2026
Никто не говорит, что указанный тут метод работы с API - это best practice. Это просто тестовые задания, чтобы понимать какие есть базовые методы взаимодействия по сети.
Rei Уровень 32
3 февраля 2026
По примеру из лекции

URL url = new URL("https://javarush.com");
URLConnection connection = url.openConnection(); // отправляем данные
try (OutputStream output = connection.getOutputStream();
   PrintStream sender = new PrintStream(output))
{
   sender.println("Привет");
}

// читаем данные
try(InputStream input = connection.getInputStream();
   BufferedReader reader = new BufferedReader(new InputStreamReader(input)))
{
   while (reader.ready())
      System.out.println(reader.readLine());
}
Почему нельзя reader.ready(): Для файлов ready() иногда «работает», но для сети поток может быть блокирующим. ready() → “можно читать сейчас без блокировки”, но это не конец потока. Если использовать while(reader.ready()), можно не дождаться всего ответа и потерять данные.
Rei Уровень 32
3 февраля 2026
👉Правильный способ: Читаем методом readLine() до null. null → конец потока. Так мы гарантированно прочитаем весь ответ, даже если данные приходят кусками.

// Создаём объект URL, указываем адрес
        URL url = new URL("https://javarush.com");
        // Получаем объект соединения. Пока соединение не установлено.
        URLConnection connection = url.openConnection();
        // Устанавливаем, что мы будем писать в поток (POST-like)
        connection.setDoOutput(true); // включаем режим отправки данных
        // ----------- Отправка данных -----------------
        try (OutputStream output = connection.getOutputStream();  // получаем поток для отправки данных
             PrintStream sender = new PrintStream(output)) {       // оборачиваем OutputStream для удобства печати строк
            // Отправляем строку "Привет" на сервер
            // PrintStream сам добавляет \n и конвертирует в байты
            sender.println("Привет");
        } 
        // ----------- Чтение данных -----------------
        try (InputStream input = connection.getInputStream();  // получаем поток данных от сервера
             BufferedReader reader = new BufferedReader(new InputStreamReader(input))) { // оборачиваем InputStream в Reader для чтения строк
            // Правильный способ читать до конца потока:
            String line;
            while ((line = reader.readLine()) != null) {  // readLine() вернёт null, когда поток закончится
                System.out.println(line);  // выводим строку на экран
            }
            // ❌ НЕ ИСПОЛЬЗУЙ reader.ready()!
            // ready() не гарантирует, что поток закончился,
            // а в сетевых соединениях может вернуть false даже если данные ещё идут,
            // что приведёт к неполному чтению ответа
Виктор Уровень 28
19 июля 2025
Тяжело, часто откатывюсь назад из за непонятого ранее.
Podaytesigy Уровень 20
27 июля 2025
Нелегко в учение, друг, легко в бою
Anonymous #3585174 Уровень 33
16 июля 2025
Like
Alex Уровень 22
28 июня 2025
Тут вопрос в другом, на фига ыообще нужна эта статья, когда в прчледней строке буквально говорится, что так делать не нужно!!! Может сначала надо ПРАВИЛЬНО учить?
Alina Gabidulina Уровень 32
25 июня 2025
В этой лекции будто редактор совсем обленился,из последней задачи: Используй методы setDoOutput(true) и getOutputStream() класса URLConnection ладно есть пару слов про getOutputStream(), но про setDoOutput(true) ни слова, я не злюсь, но просто не понятно почему нельзя сделать также как и в других случаях таблицу с методами?
Mikhail Уровень 21
5 июня 2025
Ужасный уровень! Понимания не осталось от слова совсем!
Robert Уровень 17
12 апреля 2025
Пока самый ужасный уровень. Я зашел спустя три месяца перерыва, и вспомнил почему я так давно не заходил. После этого уровня, действительно больше не хотелось продолжать заниматься на этой платформе. Я прекрасно понимаю, что одно из важнейших умений программиста - гуглить. Но тогда зачем я заплатил за подписку? Чтобы потом уйти на другие источники?
Danya Уровень 17
4 мая 2025
зайди чекни видео из ютуба,углубись в то место в котором тебе не понятно,зайди в chatgpt и там напиши какие методы и что тебе не понятно.Тем не менее тема ввода и вывода проходится в синтаксисе java и от неё не убежишь и если ты поменяешь платформу ничего не изменится ты встретишь одно и тоже
Anonymous #3552725 Уровень 32
7 апреля 2025
Установка значения setDoOutput(true) в классе URLConnection обозначает, что соединение будет использоваться для вывода, то есть для отправки данных на сервер.