1. URL class

We've studied working with I/O streams. We've studied working with files. What should we study next? What about working with the network, including the Internet? Sounds promising, doesn't it?

In Java, working with the Internet is no more difficult than working with files. Well, perhaps just a little bit.

To work with Internet resources, Java has a special class — URL. It's as simple as a stool, as you will now see.

Getting a web page

How many lines of code do you think you need to write to download some text file from the Internet and display its contents on the screen? 10? 100? 1000? Or maybe 5?

Code Note
URL url = new URL("https://codegym.cc");
InputStream input = url.openStream();
byte[] buffer = input.readAllBytes();
String str = new String(buffer);
System.out.println(str);
Creates a URL object with the path to the page
Gets an InputStream from the URL object
Reads all the bytes and returns an array of bytes
Convert the array to a string
Display the string

The contents of an HTML file will be displayed on the screen:

Console output
<!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″>
    ...

Comparing working with File and URL

URL is similar to File or Path, but Path stores the path to a resource in the file system, and URL stores the path to a resource on the Internet.

All the magic happens when we get an InputStream object thanks to a single call to the openStream() method. This is an ordinary object, and we have already studied it inside and out. Everything becomes obvious after we get the InputStream object. After all, we already know how to get data from it.

Take a look: only the first two lines are different, and only slightly. And now you can see it — the advantage of standardization and working with chains of data streams:

Working with the Internet Working with a file
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. URLConnection class

In addition to simply reading data from the Internet, we can also upload data. Uploading data is a much more complicated than reading it. You're going to need a few more methods. For example:

Code Note
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
Create a URL object with the path to the page
Create a two-way connection


Get an output stream
Put data in it


Get an input stream
Read data from it

Note that we no longer call the url.openStream() method here. Instead, we take a longer route:

  • We first establish a stable two-way connection using the URLConnection.openConnection() method
  • Then we get a stream to send data using the connection.getOutputStream() method and send data to the server
  • Then we get a stream for reading data using the connection.getInputStream() method and start reading data from it.

Resource management

Strictly speaking, we should wrap all streams in a try-with-resources block for safe handling. And it wouldn't hurt to wrap the bare InputStream and OutputStream in something more convenient. For example, in PrintStream and BufferedReader.

If we do all that, then our code will look something like this:

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. Examples of working with the network

Let's download something from the Internet. And not just download it, but save it to disk.

For example, let's write a program that saves an image from the Google homepage to disk.

In principle, there's nothing complicated here. In its simplest form, this code would look like this:

Saving a file to disk
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);

With the help of the first three lines, we receive a data stream from an Internet resource — from a picture.

In the fourth line, we create the name of the file to which we will save the image. The name can be anything, but the file extension must match the extension of the picture on the Internet. That will allow local image viewers to open it correctly.

And finally, the last line is one of the Files class's copy methods. The Files class has several of them. This method, which we used, takes a byte stream (InputStream) as its first parameter, and as the second parameter — the name of the file where the data should be written.

Theoretically, if the URL of the image were short, then this code could even be written in a single line:

Copying data from a stream to a file
Files.copy(
   new URL("https://www.google.com/logo.png").openStream(),
   Path.of("c:\\GoogleLogo.png")
);

Of course, you don't have to write it like this, but this example demonstrates how convenient and powerful I/O streams are in Java.