Your first network program
◈ 6 cardsURL.openStream() plus a stream chain is a complete web client in eight lines — and the metadata it cannot give you is exactly the argument for URLConnection in module 4.
You already have everything you need
The java.net.URL class has a method called openStream(). It resolves the host, opens the connection, performs whatever handshaking the protocol requires, and hands you an InputStream positioned at the first byte of the resource. Nothing else in this module is new — from that point it is the chaining, buffering and decoding you have just learned. A working web client is eight lines, and you can write it now.
The chain, and why each link is there
Four objects, each solving one problem the one below it created.
openStream()gives a rawInputStream. Reading it a byte at a time would cross into the network layer once per byte.BufferedInputStreamfixes that: one bulk read fills a couple of kilobytes and every subsequentread()is served from memory.InputStreamReadercrosses from bytes to characters, with the charset named.BufferedReaderturns the character stream into lines, which is the unit you actually want.
Close the outermost object and the close cascades all the way down to the socket.
Two failures, two exceptions
new URL(spec) throws MalformedURLException — a syntax failure, raised before a single packet moves, because htp://x names no protocol Java knows. Everything after it throws IOException: host not found, connection refused, connection reset mid-body. MalformedURLException is a subclass of IOException, so a single catch (IOException ex) catches both — convenient, and a worse error message, because "connection failed" and "that is not a URL" are different things to tell a user. Catch the specific one first.
The honest limitation
openStream() gives you the body and only the body: no status line, no headers. Three consequences follow immediately. You cannot see the status code, so a 404 error page arrives as ordinary content and your program happily prints it. You cannot read Content-Type, so you have to guess the charset — the UTF-8 below is an assumption, not a fact. And you cannot set a request header, so no User-Agent, no authentication, no Accept. Those three gaps are the entire reason URLConnection exists, and module 4 fills them in without changing the shape of this program.
Worked example — a source viewer
Fetch a URL named on the command line and echo it line by line:
public static void main(String[] args) throws IOException {
URL page = new URL(args[0]);
try (BufferedReader in = new BufferedReader(
new InputStreamReader(
new BufferedInputStream(page.openStream()),
StandardCharsets.UTF_8))) {
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
}
}
The try header is the chain, read innermost first. The loop is the standard reader loop: assign, compare to null, use. Leaving the block closes the BufferedReader, which closes the InputStreamReader, the BufferedInputStream, and finally the socket underneath — one close(), four objects released, even if an exception unwound the loop.
This is the skeleton A1 asks you to extend. Keep a line counter and test each line against a search term and you have a web grep; swap openStream() for openConnection() and you get the headers back. Both upgrades leave everything else here intact.