Oject-oriented programming with Java, inputs and outputs. We're going to look at the fundamentals of java.io, input and output streams, and file handling. Input and output in Java, reading and writing files, network sockets and other devices. But we're going to look mostly at inputs and outputs or reading and writing files. Java is platform neutral, so working with files can be a little cumbersome. We're trying not to be too tied to any given particular platform. However, we'll also find out that Java has evolved quite a bit. We're going to spend most of our time looking at java.io, but there's also Java's new IO and in fact there's the new IO version 2. There's quite a lot that's evolved and we'll look at different aspects of it. First, let's start off with Java IO, inputs and outputs. We talk about streams, byte streams, very similar to C and Unix. It is a logical connection to some data source or data sync to receive bytes from or send bytes to. No, don't confuse these Java IO input or output stream classes from the new Java streams that we looked at in collections and we'll revisit again here. They're brand new to Java 8. Primarily, just think of the word stream as an unfortunate name collision. They really don't have a whole lot in common other than well, data flows through them. Let's look at a simple example. We're going to read lines from a file and print them out, but with line numbers. We're going to look at the example and talk about each of the bits of code. Here, we're not looking at the whole thing, but pretty much all of it except for the class wrapper and the imports. Just at the top, we're going to quickly print out what is our current directory and we're going to get that, it is a system property called user.dir. We're going to use that try-with-resources we learned about. We're going to create a new FileInputStream looking for source/com/learnquest/demos/Helloworld.java. I don't see a leading slash, so this is relative to our current directory, which is why we printed it out. Now, having created the FileInputStream, which is byte oriented, we're going to wrap that in an InputStreamReader, which is a reader created from an input stream. Readers are character oriented. Then we're going to wrap that one more time in a LineNumberReader, which is a subclass of BufferedReader and the reason for doing that is so we can actually process line by line. Input stream gives us bytes, the reader gives us characters, and the BufferedReader of which we're using a subclass, gives us lines. Now in the pre-Java 8 days, we'd do a while loop and print this stuff out. Read the lines as long as they're not null, keep on going. But this is Java 8 and we have Java 8 streams. The lineReader has a new method on it called lines, which returns a stream of string, the new Java 8 stream and that has a forEach on it, taking this Lambda. For each line that we get out of the file, we're going to print the line number, which will get from the LineNumberReader and the line itself. Then we're done and because we use try-with-resources, not only is it a try-catch for any exceptions, but it also handles closing the file that we opened. It will close the resources that we allocated. Here's why I've already explained. The FileInputStream takes the actual file name, but we can't work with lines or even characters there. It works with bytes. We wrap that in an InputStreamReader, which now lets us work with characters and then we go with a LineNumberReader which has a readLine method inherited from BufferedReader. That can't start from a stream or even a filename it wants a reader to begin with. The reason again for using the LineNumberReader as opposed to the far more commonly used BufferedReader, we also wanted the line number, not just the ability to read the line. With respect to read the line, the method returns a null if there are no more. Again, since we're using Java 8, we went with streams and it is really much more concise in the actual Java file, which I'll show you. The forEach line is all on one line and the explanation again is that lines from a BufferedReader, the new lines method returns a stream which has a forEach method. Here's the complete program, here's our imports, this is a static import for out, just so that I can fit it a little bit better on that. Literally, that's the only reason for it is shorten the line to fit on the screen because it's long enough as it is. But here we have our InputStream and Reader. These are the more generic form, we don't need to say on the left-hand side exactly what the implementation is but we do for the LineNumberReader because that's the only way to get the getLineNumber call. Here's all the code and this is far more concise on one line than the minimum of those lines would have been. Plus, it opens the door to do other things with the stream. I'll show you another streams example of file shortly. That's our first look at file IO. The program itself is dense but very simple, and it reads, and it prints with the line numbers.