so in the previous few video we've looked at the how to read and write text files or
text data to files using the file reader and file writer classes so we
also look at buffering the data to make the program more efficient which is reducing
the disk access time by reading large chunks of the
file in to memory in the case of a read operation or writing data to a buffer
then saving a large chunk to a file in a single operation when writing so
I'll continue to use buffered streams in this next example and here we are gonna take
a look at byte streams of binary data in other words now once again we need
some data to work with so what we'll do is we'll continue using our locations
data for this first example but once I have covered how to read and write binary data we are gonna switch over
and use some different examples so you don't get to bored so to clarify what's going
on with the static initialization block in the locations class just open that up
in the static block you can see on the screen when we run like locations.main
the main method in this class this is the code up here on line 14
when we run that main method the class has to be loaded before its main method can be
executed so what that means is the code in the staticp initialization
block is executed before the main method and what that means is that the
locations and directions files have been read in before the main method is executed
in this class so to start with what I'm going to do is rewrite the main method to save
the data that's read in by the static initialization block in a binary format
now once we've got a binary file to experiment with and what I'll do is change the
static initialization block to read from this newly created file now in terms of
binary data one advantage of dealing with that data or byte stream is that we
don't have to pass the data into the various data types that were stored and
the reason for that is a byte stream itself can be used to read and write any of the
java primitive types that such as int double byte etc and also a
special case it can also handle string variables even though
a string isn't actually a primitive type
and I think that's pretty cool so working with byte streams they follow the
same pattern or working with byte streams follows the same pattern the differences is
were used to file InputStream and the file output stream classes instead of file readers
and file writers once again I'm gonna buffer the data using the buffered
InputStream and buffered output stream classes now in terms of doing this we could work
directly with these objects but they only handle raw bytes so reading or
writing either a single byte or a specified number of bytes now there are
occasions when that's probably all you'll need but generally speaking when storing
and retrieving data you probably want to work with Java types now the Java IO
package likely for us makes it easy by providing the data InputStream and
data output stream classes and they provide methods such as read int to read an
integer value from the stream it does this by reading 4 bytes from
the stream and building up the integer from those 4 bytes so have a look at how those
classes work together in a minute but it's probably easier to have some code
to work with so we are gonna replace the code in the locations main method now
with this new code instead of trying to change it I'm going to just delete everything and
start again just so it's clearer for you so do try and its gonna be data...
....
...and notice how IntelliJ is finding that for us
automatically which is pretty cool....
....
...
....
...
...which we effectively to write a string and you can see the input their is
looking for is a string so....
....
...
....
...that is how many exits were writing for this particular
location so lets now write that number out so....
....
...
....and we don't want to record the quit and that is why
we deducted one from the total size so....
....so if we are not writing the quit location or making sure the direction that we're
processing isn't quit then we are gonna print this out so....
...
....
...which is current the current direction we are
processing and...
....and we want to write the location effectively where
with that direction goes so....
...
....
...
....you may as well try and use that try with exception now in the course
because that is the recommended way to process and of course that means we don't need to have
that finally and catch
we are already throwing the IO exception anyway we don't have to worry because of
course as if you recall this is automatically set up to close our
files when we finish processing them and just one thing to note we're going to be
writing locations.dat because it's no longer a text file
2 advantages firstly it's needed anyway because the main reason we doing that is
not conflict with locations.txt but equally importantly it's clear that
this isn't a regular text files so we wouldn't want to call it .txt and people thinking they can open it with a
text editor when of course when it is a binary data and it won't open so that's one reason
why we've chosen that so lets run this program and see if it works
and you can see we got a locations.dat file now and just out of interest if we try and open that IntelliJ having a bit of a fit
but we just say treated it as text anyway and open it you can see it looks a little bit
like their is some weird stuff in there as well
and if you click on reload and another encoding we get the same result
I am not gonna proceed with that the bottom line here is that IntelliJ is seeing that
this is not a regular text file compared to say locations.txt which of
course you could read because that was a text file but this is a binary file so we
still get to see some of the information but you can see in the case of line 1
those bytes there are ultimately going to be an integer which corresponds
to the first thing we wrote out which was the location ID and just in terms
of see where we're up if we go back and scroll up to the top here after the imports which happened in
this static initialization block
....you can see writing locations 0 where the location was sitting in front of a computer
learning Java writing 0 exits because their weren't any exits location 1 and we got various directions and the location
or the direction corresponding to where which room that goes or which location that goes to
so that's the text representation of what's been written in
the binary file and i do recommend when you working with binary data like this is
generally a good idea to do something like this and to keep your code up to date
so getting back to the code again so if I closed this file its a good idea as you're writing your code to
have this sort of debugging capabilities built in and adding and updating as you
update this particular method if you're writing data or adding new data to the file update your debugging information as
well because it really makes it easier to work on this in the future now later
in the course I am gonna look at logging because really if you think about this output shouldn't
really be shown to users of the programs so its better to write it in a log file where it's
hidden from users but is available to us as developers if we need to diagnose
those errors in the future so you notice we created the dat file that was the
number one but secondly did you pick up the fact that we now writing
locations and exits all in the same file because locations have different numbers
of exits the number of exits is written first and followed by the exit data
for that location if you think about it there's no reason why we couldn't have
done that for the text files as well but it was useful to see how data from different
files could be related and that's the reason that I used that different approach
in the case of the text files they can also be really read by humans so its
worth spending time to decide how the data should be presented in that case you
know whether a single files is ok or split into locations and exits as I did
when working on the text files once again you can make arguments for
and against this approach but in the case of binary data humans wouldn't be reading the contents
of the file so the decisions probably a lot easy-to-make so the question to ask
yourself here's why used 2 separate files
when a single file will do especially if using two separate files
doesn't give you any advantage you may feel that having 2 separate files makes the code
easy to debug in which case it's fine to do it that way it's your code after all
so you can really do whichever you want but it is a good idea to understand the
options when making a decision but actually it also looking at the code line 13
through 24 is not really a lot of code there anyway so I mean it's not
particularly complex what we've done sort of writing this out to a single file and
again just looking at that code you can see that the code to write to the byte stream
is very similar to writing to a character stream the file output stream objects
used to open the file for writing and once again we buffer the output as you saw
with the buffer output stream object now I could have left it at that and I could have written a code to produced the bytes
representing the integer string values to be written its a bit fiddly doing that
way but not too difficult but fortunately the data output stream
class deals with all that automatically and you saw that as I was typing code in all we will have to do
here now is to write it in for example to use the .right int method you saw that on line 15 and
then write UTF on line 16 is an example to write the string out the good news is
there are also methods to write out all the Java primitive types so the data output stream class includes
the right long right flow
right double etc so lets spend a short while looking at what the right int method
does so going to command click so you command or control-click
right int click under that then there's the method on the screen so notice here we are using this particular operator
this is called the shift right 0 fill operator which is a bit of a mouthful
but basically what is doing their by using 24 in the expression here it's actually moving the top eight
bits the highest bytes into the lowest position by shifting them right 24
places if that make sense so open up an image and show that on the screen to make a bit more
sense of this so lets have a look at this on the screen
so in the example on the screen here the original value is 922.342.959
I wanted to show you how the various shift operations result in the four bytes been
extracted for writing to the file so can see here by using that first
I'll just move this here so you can see this as well
corresponding to the liens of code that is right int is using
you can see in the first case right shift by 24 bits result in the values 0011 0110 which is hex 36
or 54 in decimal been moved to the right most byte with all other bytes
containing 0 and as we move down the next shift operation shifts right 16 bits
that's the 16 here on line 198 and so we get 36F9
you can see the number there in binary it actually gives us 0011 0110 1111 1001 in
binary and just about the maximum number of digits I'm prepared to read out so I'm
gonna give all the remaining so shifting right by 8 when the next line
causes the to f values to fall off to the right and we get 36 F9D6 you can see this on here
the third example and the following shifting right 0 place does nothing
and the values is unchanged so because only the single right most bytes should be
written each time the shifted values is ended with the hex value FF which is
000000FF when stored as an integer so that results in higher 3 bytes being cleared to 0 given
the value that must be written to the file and you might be looking at that and thinking
Tim what the heck out are you going about here the point I want to make with all of this is because we've got the data output
class or the data output stream class we don't have to worry about any
of this but they could be situations where you may have to deal with raw data
streams at some point so it's probably useful to understand what's going on
now we can do that without getting too bogged down in binary so in the next video
I'm going to create a new java file to hold a class called shift int and we are going to print
some values out that ultimately will be written out just so we can see what's
happening at a lower level than you probably used to so lets work on that in
the next video