1. URLklasa

Studiowaliśmy pracę ze strumieniami we/wy. Studiowaliśmy pracę z plikami. Co powinniśmy studiować dalej? A co z pracą z siecią, w tym z Internetem? Brzmi obiecująco, prawda?

W Javie praca z Internetem nie jest trudniejsza niż praca z plikami. No, może tylko trochę.

Aby pracować z zasobami internetowymi, Java ma specjalną klasę — URL. To jest tak proste jak stołek, jak teraz zobaczysz.

Uzyskanie strony internetowej

Jak myślisz, ile linii kodu trzeba napisać, aby pobrać plik tekstowy z Internetu i wyświetlić jego zawartość na ekranie? 10? 100? 1000? A może 5?

Kod Notatka
URL url = new URL("https://codegym.cc");
InputStream input = url.openStream();
byte[] buffer = input.readAllBytes();
String str = new String(buffer);
System.out.println(str);
Tworzy obiekt URL ze ścieżką do strony
Pobiera InputStreamobiekt z adresu URL
Odczytuje wszystkie bajty i zwraca tablicę bajtów
Konwertuje tablicę na łańcuch
Wyświetla ciąg

Na ekranie zostanie wyświetlona zawartość pliku HTML:

Wyjście konsoli
<!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″>
    ...

Porównanie pracy z FileiURL

URLjest podobny do Filelub Path, ale Pathprzechowuje ścieżkę do zasobu w systemie plików i URLprzechowuje ścieżkę do zasobu w Internecie.

Cała magia dzieje się, gdy otrzymujemy InputStreamobiekt dzięki pojedynczemu wywołaniu metody openStream(). To zwykły przedmiot, który już zbadaliśmy od wewnątrz i na zewnątrz. Wszystko staje się oczywiste po otrzymaniu InputStreamobiektu. W końcu wiemy już, jak uzyskać z niego dane.

Spójrz: tylko dwie pierwsze linijki różnią się i to tylko nieznacznie. I teraz to widać — zaleta standaryzacji i pracy z łańcuchami strumieni danych:

Praca z Internetem Praca z plikiem
URL url = new URL("https://codegym.cc");
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. URLConnectionklasa

Oprócz prostego odczytywania danych z Internetu, możemy również przesyłać dane. Przesyłanie danych jest znacznie bardziej skomplikowane niż ich odczyt. Będziesz potrzebował jeszcze kilku metod. Na przykład:

Kod Notatka
URL url = new URL("https://codegym.cc");
URLConnection connection = url.openConnection();

// Get a stream for sending data
OutputStream output = connection.getOutputStream();
output.write(1); // Send data

// Get a stream for reading data
InputStream input = connection.getInputStream();
int data = input.read(); // Read data
Utwórz obiekt URL ze ścieżką do strony
Utwórz połączenie dwukierunkowe


Uzyskaj strumień wyjściowy
Umieść w nim dane


Uzyskaj strumień wejściowy
Odczytaj z niego dane

Zauważ, że nie wywołujemy już url.openStream()tutaj tej metody. Zamiast tego wybieramy dłuższą trasę:

  • Najpierw ustalamy stabilne połączenie dwukierunkowe za pomocą URLConnection.openConnection()metody
  • Następnie otrzymujemy strumień do wysłania danych za pomocą connection.getOutputStream()metody i wysłania danych na serwer
  • Następnie otrzymujemy strumień do odczytu danych metodą connection.getInputStream()i zaczynamy z niego odczytywać dane.

Zarządzanie zasobami

Ściśle mówiąc, powinniśmy owinąć wszystkie strumienie w try-with-resourcesblok, aby zapewnić bezpieczną obsługę. I nie zaszkodzi owinąć gołą InputStreamiw OutputStreamcoś wygodniejszego. Na przykład w PrintStreami BufferedReader.

Jeśli zrobimy to wszystko, nasz kod będzie wyglądał mniej więcej tak:

URL url = new URL("https://codegym.cc");
URLConnection connection = url.openConnection();

// Send data
try (OutputStream output = connection.getOutputStream();
   PrintStream sender = new PrintStream(output))
{
   sender.println("Hello");
}

// Read data
try(InputStream input = connection.getInputStream();
   BufferedReader reader = new BufferedReader(new InputStreamReader(input)))
{
   while (reader.ready())
      System.out.println(reader.readLine());
}

3. Przykłady pracy z siecią

Pobierzmy coś z Internetu. I nie tylko pobierz, ale zapisz na dysku.

Na przykład napiszmy program, który zapisze obraz ze strony głównej Google na dysku.

W zasadzie nie ma tu nic skomplikowanego. W najprostszej postaci ten kod wyglądałby tak:

Zapisywanie pliku na dysku
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);

Za pomocą pierwszych trzech wierszy otrzymujemy strumień danych z zasobu internetowego — z obrazu.

W czwartej linii tworzymy nazwę pliku, do którego zapiszemy obraz. Nazwa może być dowolna, ale rozszerzenie pliku musi odpowiadać rozszerzeniu obrazu w Internecie. Dzięki temu lokalne przeglądarki obrazów będą mogły je poprawnie otworzyć.

I wreszcie ostatnia linia to jedna z metod Filesklasy copy. W Filesklasie jest ich kilka. Ta metoda, którą zastosowaliśmy, InputStreamjako pierwszy parametr przyjmuje strumień bajtów ( ), a jako drugi — nazwę pliku, do którego mają zostać zapisane dane.

Teoretycznie, gdyby URLobraz był krótki, to ten kod mógłby być napisany nawet w jednej linii:

Kopiowanie danych ze strumienia do pliku
Files.copy(
   new URL("https://www.google.com/logo.png").openStream(),
   Path.of("c:\\GoogleLogo.png")
);

Oczywiście nie trzeba pisać tego w ten sposób, ale ten przykład pokazuje, jak wygodne i wydajne są strumienie I/O w Javie.