so hope I haven't freak you out to much from the last class when we went into
all this detail about what this right int
does and shifting right and all this sort of stuff but I am alluding to
something I'm getting to something that I want you to look at because it's
really useful to understand what's going on at the low-level its not something you
need to do all the time but it's there if you need to so what we are gonna do is we are gonna create a
new class class and I'm gonna call this one shift int...so just wanna go through
this little bit more and what I'm gonna do is paste in code in rather
than typing it and this code will be available in the Resources section the reason I am pasting it in
and it hasn't really got anything to do with the IO section I'm just using
it to show the 4 values that the right int method produces when it saves an
int value to the binary streams so their is no advantage to you see me type this
I'm just going to copy this code and paste it in and again you can get
this code in the Resources section of this video so you can do the same thing that I
pasting that I did a so you can see I've created my own right int method and that's based on
the right int method that was on screen at the start of this video but what I've done also I've used
the display method to do some formatting so the output is easier to read and I've also use a
technique that may not work on some windows versions to show the right most
8 bits in a different color to make it easy to compare the values with the values
their produce from so if we actually run this program now and you can see the
values on the screen so the program as you can see hopefully works on your Windows
computer to if you got one it colors the last 8 bits purple and it works on a Mac
and will also work on Linux distros and it also works on Windows 10 there's a chance it won't work on
earlier versions the code itself will still run but you might actually see
strange codes instead of the color change I've got the binary data showing
purple on the screen so I've included the
constants for other colors as you can see on the screen there in case you want to do
this for console app but again you might want to remember that hasn't been tested
on version of Windows early than windows 10 it should work but we haven't tested that
bottom line is if it doesn't you might want to try changing some of these
colors so we got ansi purple using ansi purple in here and the ansi reset command so try using instead
of purple try using some other classes and see if it works if and only if you're having difficulty
getting this to work so you can see that the original values written to the file
as the 4 bytes 54 219 this numbers here to the left hand 214 and 47
the output shows how those values were obtained by shifting the binary number
right then masking of all but the right most 8 bits and that's what the code
here on line 27 the & 0xFF that's what that's actually doing so this seemed
really complicated then don't worry the data output stream class does take care
of writing Java primitive types and there's also a corresponding data input
stream class that reads it back in again and in fact lets switch over now and
start having a look at that in other words reading that binary data that we
created in the previous video back in so say goodbye to shift int.java ok so geting back to
locations.java so we got our main method now that we're used to create the location.dat file
and of course that used the binary output stream classes to do that now reading
it back in again
actually easier than reading the data from a text file and it's because we
don't have to do any string parsing to get the integer values so the data input
stream class takes care of building primitive types such as int and double from the
bytes in the file
so what we're gonna do is comment out the existing code in the static initialization
block I'm going to add some new code to read from the binary file so I'm going to comment a
lot out in the static initialization block in our locations.java
right down to the end of the method
and back up to the top and add some code so the code is going to be
try...
....
....which was the file that we created
in the last video ok so that is our try with resources...
...so we are going to break out of that loop once we finish processing the data so.....
....
...and with this one what we will do is catch an IO exception because we're not throwing so....
....
......next we need to determine the number of exits so...
....
....so now we know how many exits their are we can use a for loop so...
....
...
....
.....and then outside of the loop after we got all exits we can
then save this entire locations so.....
...
....and we already caught any potential exceptions and that's all that exists in terms of
code so you can see our version I've commented out its longer than what we've written
and I think you'll agree that this is also a tidier and its because
there's no parsing of the data required it just read the integers
strings using the methods in the data InputStream class so just to confirm the
code reads in the location ID the description and the number of exits from
that location and the exits is going to get read back in using a for loop as you saw
me code on line 42 but one strange thing you might have noticed is that the loop while
true which I've started on line 35 hasn't gotten an apparent
exit condition to terminate the loop and in fact if we come over here we are getting an error
from IntelliJ and if we open that up while statements cannot complete without throwing
exception so this isn't a particularly good way to write code hence the warning
but if you attempt to write this by just referring to some of the examples on the
internet or even in the Java documentation then this seems to be a
reasonable way to do it but before going into more detail in that lets run the
program to make sure it still works so in here we want to remember that we don't
execute the main method from the locations class we did that in the
previous video so that we could create the locations.dat file but what
want to do now is write it on the main method from the main class so we are going to
test that the program is working go back to main class and right click and run and try a few directions to
make sure its working we got west east
up down and quit that seems to be working OK and just to confirm again that the code in the static
initialization block in our locations.java that was executed of course when the
locations class is loaded from the main method in the main class now the Java
documentation should be read carefully before applying it to your own code and its quite easy to pick up on
the fact that the data stream readers throw an IO exception when there's no
more data to be read from the stream and in actual fact they throw a sub class
of exception called EOF exception and we should really be checking for that as a way to
terminate the while loop rather than just using the IO exception as we've done
this code and just to confirm just to run this again run the main.java method run that
again down here IO exceptions so you can see that the code was executed the code that we added I
just disconnect that from our locations.java in the static
initialization block this exception was caught here we caught that and we
outputted that as an IO exceptions
but the point I'm making here is that how we've done this this isn't really the best way of
terminating the while loop and that's because the IO exceptions are going to cause the
problem to jump out of the while loop and be caught in the catch block but the
code really is messy and for example what happens if an IO exception is raised
for another reason than the end of file so its very difficult to treat a real
exceptions such as the input file not being found or having insufficient
permission to allow us to open it differently to the end of file
being reached you know which you know is an expected event very few data streams
are infinite after all so the point is it's very easy to cause an exception but
we'll just try to read the binary data from a file that doesn't exist by changing
the file name up here on line 34 just to sort of simulate what happens so
instead of locations I'm going to call it locations.dat and go back to the main method and run again
we got something different we get an exception null pointer exception which would expect because the
file doesn't exist and you can see that obviously IOException was printed
so the code in the catch block did execute but if you were debugging this was
because the data stream run out of bytes or some other reason now we added
detail and time-consuming investigation we've got no ideas we would really want to
do this using a better mechanism to try to determine what the error was so the way to
fix that is going to close this down and go back to the locations class and what I'm going
going to is add another try block and some few other lines as well so within in the first try block we add...
....
....and once we've done that we got no other errors so looking at that now you can see we've
got a boolean end of file equals false we gonna keep going until while end of file
so we are gonna keep going until EOF is equal to false if we do hit
the end of file exception which was again is generated automatically by these classes
when it reaches the end of input we gonna set that to true which will then exit the
while loop automatically so other words it causes the while loop to terminate to
terminate nicely but the other good point here is that any other exceptions
is gonna be caught by the try with resources catch block the outer one and if
you go back to main.java and run again we see that we've still got that error because we got the file name wrong
we change the file name to a file that doesn't exist so if your are debugging this you know that the
problem isn't caused by the input stream running out of data now obviously in
production code you do more than a print a message in the catch block we would be
logging the error and the file name is the minimum we consider probably doing
just to make sure this work lets go back to locations.java and change
our file name to the correct name again locations.dat go back to
main.java then right click and run this and we can see the code is now still working nicely so working with byte streams their is really
no more complicated than reading and writing character streams but you do have to
know the format of the data that your reading now in this example we knew when to use read int and when to use read
utf and that's because we'd written the original file so its just a case of using the
corresponding read methods in the same order as we used to write methods so
provided you know the format of the data reading from byte stream is straight
forward now of course we also had
to know the format of the text file so that we knew when to try and convert the
data to an int but in the case with text file is generally easy to open it in text editor and work out the format of the
data and of course as we have established when we open the binary data file in the
previous class that's not so easy to explore for example a sequence of 4
bytes in a binary file could be single int value 2 shorts or 4 bytes for example and you
wouldn't know that if you weren't to involved in the process that created that
binary file and as a result you want to know the format of the data by reading the specifications for the
system that produced that binary file so you can write the code to import and read
in that binary data so as I mentioned byte streams can be used when dealing with
Java primitive types in the next video is we are gonna have a look at
how to handle binary IO when dealing with objects see you in that next video