- [Man] All right, so continuing on from the last video,
what we need to do is finish off and add the code
to the static initializer block
to process the exits, the directions.
So we're gonna do this below the first try,
the first try with the resources block.
So we're gonna do it down there,
and we're gonna start with try,
and it's gonna be BufferedReader.
D-I-R file equals, that's gonna be Files dot
newBufferedReader again
and D-I-R Path this time.
Then we're gonna do a String input.
And: while input equals D-I-R File
dot readLine
while that's not equal to null.
And I got that wrong.
It's the parentheses, slightly wrong with that.
It should be one parenthesis at the end of the line
and an extra parenthesis to the right
of the D-I-R File dot readLine.
All right, so then we're going to do a string array.
Data is equal to input dot split
comma.
And then we're gonna do:
int loc is equal to Integer dot parseInt,
and that's gonna be data zero.
First element.
So string, then direction equals the second element,
so equals data one.
And int destination is equal to Integer dot parseInt.
Then the next element, data two.
Let's just print those out then.
So I'm gonna print out loc plus colon plus direction
plus another colon, space, then plus the destination,
just so that we can see it is being retrieved okay.
And next we're gonna create a location.
So: Location location equals locations dot get loc.
So we're using that as the key to get it,
the loc, the first element
that we retrieve for the location.
Then we want to add some exits.
So location.addExit.
That's gonna be direction, destination.
Okay, and then to get rid of that other error at the top,
both errors, we need to catch the IOException.
And we need another right curly bracket there.
Catch and e dot printStackTrace.
And I'll just tidy that up.
Okay.
And of course that should have been newBufferedReader,
because we're reading not writing.
Okay.
And I seem to be having a bad day with coding.
We've got an extra one in there.
So I'll just reformat the code again.
And that should be good to go.
Nothing needed to be changed.
Okay.
So even though we topped in a lot of code,
really the only thing we've changed here
is the files that newBufferedReader method call
in both try statements.
Also we had to declare the two path variables.
Otherwise the code's pretty much identical to what it was
when you called the BufferedReader constructor
directly in the two try statements.
Now, as I mentioned before,
when you use the Files.newBufferedReader or Writer methods
to create the buffered reader and buffered writer,
the underlying instance used to do the IO
is a Java.nio instance rather than a Java.io instance.
All right, so what about reading and writing objects?
Well firstly,
there isn't a Files dot newObjectInputStream
or Files dot newObjectOutputStream method.
But there are new input stream
and new output stream methods,
which return an input stream
and an output stream respectively.
So, in other words,
you can construct an object input stream
from an input stream
and an object output stream from an output stream.
So, with that said, you should be able
to create an object input stream or an output stream
from a path using a two-step process.
So you call the files method to get the appropriate stream
and then call the object input stream
or object output stream constructor directly
using the stream you got from the files method.
Sounds like a mouthful,
but let's actually try that to see how it works.
All right, so this time you're gonna be writing and reading
the locations dot dat file.
Now you no longer need two files,
because you're gonna serialise the contents
of every location object
to the locations dot dat file.
So, to do that,
we need to go into our locations dot main method
to write the file.
So I'm gonna go back up there.
So we're in Locations and looking at this main code.
So what we're going to do here
is we're going to just comment this code out
to show you how to do it using objects.
So we're going to comment that out entirely
so we've got a copy of it.
And I'll actually start coding at the top.
All right, so again we're working now
with locations dot dat.
So I'm gonna start by typing:
Path locPath is equal to FileSystems
dot getDefault
dot getPath.
This time, as I said, it's locations dot dat.
Then we just do a try.
We start with an ObjectOutputStream locFile
is equal to new ObjectOutputStream.
Then we do a new BufferedOutputStream.
And then we pass to that the Files dot newOutputStream
and the location path.
And in terms of writing it out,
it'll be code that you've seen before.
So for location:
Location location colon locations dot values
locFile dot writeObject
location.
So the two things to notice with this code.
First of all,
you're using the Files dot newOutputStream method,
this one up here on line 21.
We're using that to get an output stream
using a path instance,
because passing locPath,
of course that's using the path,
the Java.nio path object,
or path instance I should say.
And secondly, what we're doing is exactly what we did
when we created a file output stream
using the file output stream constructor.
So you're wrapping it up still in this BufferedOutputStream.
So the IO will be buffered.
Then you're wrapping that in an ObjectOutputStream.
So really the only change you've made to the code
is to call the Files dot newOutputStream
rather than the file output stream constructor.
So that's where the Java.nio code comes in.
All right, so we've got an existing location dot dat file.
If we wanted to, we could delete it.
But we're just going to run it again.
And it should be recreated.
So let's run that.
Okay, the code has been written.
And the static initializer block also was executed,
which in case you were wondering
where that output had come from.
Obviously we didn't have any output here
for locations dot dat while we were creating that.
All right, so now that we've done that,
let's now modify the static initializer
so that it uses the Files dot newInputStream.
So let's go down and have a look at that.
And the code is going to be a lot easier,
because we're reading objects
instead using delimiters and so forth
to retrieve the data.
So I'm gonna copy that all,
comment that out.
And let's have a look at it.
The code to do that now:
Path locPath
is equal to FileSystems
dot getDefault dot getPath.
This time it's locations dot dat,
which you've just created in the main method
for the locations class.
And now we're gonna do try.
And it's going to be ObjectInputStream this time.
And locFile is equal to new ObjectInputStream this time,
new BufferedInputStream
and Files dot newInputStream locPath.
All right, then let's write the code now to get the objects:
boolean E-O-F equals false.
And then we'll do a while and not end of file.
We want a try there.
And we're gonna catch the end of file exception.
And we'll put E-O-F equals true for that whole exception.
And the code in here is gonna be:
Location location equals,
casting it to location
locfile dot readObject.
Then we want to do locations dot put
location dot getLocationID comma location.
And we've got another exception that we need to catch here.
And another one here.
Because, if you remember the code
when we've done this previously,
we had a number of exceptions.
We do a catch.
This one is InvalidClassException.
We get that and we'll just print out a message.
InvalidClassException
plus e.getMessage.
You could have just put it down the stack trace
if you wanted to.
We also want to catch the IOException.
For that, we print out the message as well.
And then the third one we do want to catch here
is the ClassNotFoundException.
ClassNotFoundException.
And that was going to be ClassNotFoundException
e.getMessage.
So the code is very similar,
almost identical to what we used previously
to read objects from locations dot dat,
except we're using the Files dot newInputStream
up here on line 51,
using that method to create an input stream.
And then we're wrapping that with a BufferedInputStream.
And then we're finally wrapping that
with an ObjectInputStream.
Okay, so if we run that,
we should find that our code still works.
And obviously we're not getting any errors,
which is a good thing.
We're also not getting any output anymore,
because we didn't put any debugging code in our main code,
but also not in our static initializer block either.
So, essentially you can use Files dot newInputStream
and Files dot newOutputStream to create any stream
that descends from input stream
and output stream respectively.
All right, so at this point you now know how
to use Java.nio classes
to create commonly-used Java.io streams.
In the next video, we're going to start looking
at how to read and write text files
using Java.nio exclusively.
And if you recall, a few videos ago
I said that doing IO using Java.nio
means the data is processed in blocks
rather than one byte or character at a time.
So, to accomplish this, Java.nio uses channels and buffers
and sometimes selectors.
So let's start looking at channels, buffers, and selectors
in figuring out how to use Jave.nio to do all our IO
in the next video.