JavaRush /Курси /Java Syntax Zero /Робота з мережею

Робота з мережею

Java Syntax Zero
Рівень 16 , Лекція 7
Відкрита

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.


Коментарі (8)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Viacheslav B. Рівень 1
5 квітня 2024
цей урівень треба читати або два рази або починати з кінця, хто знає - це мабуть така логіка у автора була !
Olexandr Рівень 47
24 січня 2024
Там де частина - Контроль ресурсів і приклад коду - сдається мені, що код працювати не буде, без розблокування потоку виводу... Це я останню задачу робив, точно знаю тепер😃
Sava_crosava Рівень 23
25 жовтня 2023
Раджу ознайомитись із статтею https://javarush.com/groups/posts/4039-vvod-vihvod-v-java-klassih-fileinputstream-fileoutputstream-bufferedinputstream тоді вже можна освідомленно розвязувати задачі) лекція не те щоб жахлива але не повна, застаріла, не розкрита, не цікава, ну можливо все ж жахлива(
Andriy Рівень 26
24 червня 2023
"отримати об'єкт типу InputStream. А це стандартний об'єкт, і ми його вже вивчили вздовж і впоперек" Як прочитав, то так сміявся, що аж щоки боліли. Ага, звісно, "вивчили вздовж і впоперек" 🤣
Shura Рівень 20
22 липня 2023
теж розсмішило це вздовж і впоперек )). і коли, цікаво, ми це встигли
Ihor Prokudin Рівень 51
29 березня 2023
Вже простіше ніж попередні лекці
FAUST_ua Рівень 29
12 вересня 2022
Де до першої задачі пояснено 2 останні строчки коду розв'язання?
Yurii Sakharuk Рівень 27
25 травня 2022
Жахливий весь блок про ІО. Інформація подається непослідовно, перескакуєте від класу до класу без послідовності та нормального пояснення, частина матеріалу не актуальна, задачі не відповідають інформації з лекцій.