Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Well done!
You have completed Java Data Structures!
You have completed Java Data Structures!
Preview
Let's create a hand-rolled way to add and share songs via editing a text file. We'll save and load our songs.
Resources
Copy/Paste
Michael Jackson|Beat It|https://www.youtube.com/watch?v=SaEC9i9QOvk
Jackson 5|I want you back|https://www.youtube.com/watch?v=auaqyVYmpP8&list=RDauaqyVYmpP8&start_radio=1
Jackson 5|ABC|https://www.youtube.com/watch?v=1VIHgW0C7p4&list=RD1VIHgW0C7p4&start_radio=1
Journey|Don't Stop Believin'|https://www.youtube.com/watch?v=c8wn2fMYvns&list=RDc8wn2fMYvns&start_radio=1
Wilson Phillips|Hold On|https://www.youtube.com/watch?v=UJP_mVu48OU
Taylor Swift|Shake It Off|https://www.youtube.com/watch?v=-i5MU14JLdw
Katy Perry|Roar|https://www.youtube.com/watch?v=hMF4h0gYN-0&list=RDhMF4h0gYN-0&start_radio=1
Ritchie Valens|La Bamba|https://www.youtube.com/watch?v=UmfyX7v99Ug&list=RDUmfyX7v99Ug&start_radio=1
U2|With Or Without You|https://www.youtube.com/watch?v=Hd-7ALoXKNQ&list=RDHd-7ALoXKNQ&start_radio=1
U2|I Still Haven't Found|https://www.youtube.com/watch?v=umkNSv1fNXw&list=RDumkNSv1fNXw&start_radio=1
Jackson 5|Rockin' Robin|https://www.youtube.com/watch?v=sbk_g0NR-NU
The Cure|Friday I'm in Love|https://www.youtube.com/watch?v=eNQE0n5_6pE&list=RDeNQE0n5_6pE&start_radio=1
The Cure|Boys Don't Cry|https://www.youtube.com/watch?v=UcUKoH5t-vM&list=RDUcUKoH5t-vM&start_radio=1
The Cure|Just Like Heaven|https://www.youtube.com/watch?v=eVSP_8-gkyQ&list=RDeVSP_8-gkyQ&start_radio=1
The Cure|Love Song|https://www.youtube.com/watch?v=Mprq_HO1T3I&list=RDMprq_HO1T3I&start_radio=1
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
We saw earlier
a way to use the serializable marker
0:00
interface
to serialize Java objects in and out.
0:03
Now, ideally, this karaoke machine
would be backed by a data source
0:07
like a database, but we're just proving out
our MVP hypothesis.
0:11
I think we can probably kick out
our own custom serialization and provide
0:15
a clear enough format that we can actually
enter songs manually to a file.
0:19
Here, let me show you what I mean.
0:24
So, as an admin,
I should be able to save the songs
0:27
that have been entered so that I do not
need to recreate it every time.
0:30
Here we go. Alright.
0:33
So let's write out those songs
using a custom serialization format.
0:35
Now I'd to keep it in a format
that's easy to edit by hand.
0:41
That way, we could actually share the file
0:45
and curate an awesome
list of great karaoke songs.
0:47
So first, let's add
the ability to export our songbook.
0:50
Let's
put it right here under the constructor.
0:54
It doesn't need to return anything,
but it should take a file name.
0:56
So we'll say export to string file name.
1:00
In our try with resources block
here, we'll do
1:09
try and we'll make a file output
stream named FOS.
1:11
So new file output stream,
1:21
and we'll pass in the file
name that we got, right?
1:25
So that's going to create a new file,
and we'll create a print writer
1:29
and pass in the file output stream.
1:32
Great.
1:41
Okay, so in the try block,
what we're going to do
1:42
is we're going to loop the songs.
1:44
So we'll say for song in mSongs,
1:46
so that's every song we have.
1:51
We will do writer.printf.
1:55
And here's the custom format.
1:58
Let's separate each one of
these properties with a pipe symbol.
2:00
The pipe symbol's again right
above the enter key on most keyboards.
2:04
And I'm going to end it with a new line.
2:07
Okay? So that's the format string.
2:09
and let's make that be
2:13
song.getArtist, song.getTitle,
2:15
and then song.getVideoURL.
2:23
So that's ending our for loop
2:31
and this is ending our try block
2:34
and we're going to catch an IOException
2:39
So if we couldn't
2:47
write to the file or it was protected,
we throw one of these.
2:47
We'll write problem saving
2:51
percent s
2:55
new line and we'll pass our file name.
2:56
As usual, let's print out the stack trace
just in case
3:00
that happens.
3:03
Okay, so let's add the inverse of that.
3:06
Let's allow our songbook
to be loaded from a file.
3:08
So that's also not going to return
anything, and we'll call it import from,
3:19
and it'll take in a file name again.
3:23
So we'll do another try block
3:27
with resources.
3:29
and much like before,
3:32
we'll do a file input stream,
3:34
FIS, and it's a new file input stream,
3:36
and we'll pass in the file name.
3:41
Let's do another one of those buffered
3:45
readers,
which we were using earlier, same class.
3:47
This time instead of reading from system
it going to read from that file
3:50
So in the same sort of pattern
we're going to say a new input stream reader
3:55
We're going to pass in the file input stream
this time instead of system.in
4:00
and close that off.
4:04
So what we're going to do here is we're
going to read line by line from that file.
4:07
So let's first declare a variable
that we'll use.
4:11
Let's name it line.
4:13
This is a little bit of wacky syntax here,
4:16
but I want you to see it because
you'll see it when searching stuff online.
4:19
So I'm going to create a while loop
and I'm going to add
4:23
another set of parentheses in here.
4:25
Inside of these inner
4:31
parens, I'll assign
line equals reader dot read line.
4:32
Now read line, the way that that works
is if nothing comes back, it's a null.
4:36
So it will be the value of whatever
came from read line will go into line
4:40
and will also be available
outside of here.
4:44
Now we can say not equal to null, right?
4:47
Because when read line is done,
it will be null at the end.
4:50
Okay, so each line we're going to be
getting back is formatted
4:54
with those pipe characters
separating each property, remember?
4:57
So we're going to get one long
string back from our file,
5:01
and we want to split it up
where those pipes are.
5:04
Well, luckily, there's a method on strings
that we use called split.
5:07
And if you're unfamiliar, it's
used to divide a string into an array of
5:11
substrings based on a specific delimiter,
which can be a regular expression.
5:15
If you're unfamiliar
with what a regular expression
5:20
is, it's a sequence of symbols
and characters expressing a string
5:22
or pattern to be searched
for within a longer piece of text.
5:26
Let's just write this out real quick.
5:31
So this split method returns an array,
so we'll go string array,
5:33
and we'll name it args for arguments,
5:39
which is how we're going to be
using these momentarily.
5:41
Set it equal to line, which is our string
5:44
being read, dot split.
5:46
In the parens is where we add
our regular expression, or regex.
5:50
So, for example,
5:54
if you had a string with a bunch of words
separated by commas, you could just put a
5:56
comma in your quotation marks here,
and that would work.
6:00
Unfortunately, in our case,
the pipe character
6:03
has a special meaning in regex,
so we need to escape it
6:05
so it understands we really mean split it
at this pipe symbol.
6:09
In Java regular expressions,
we need to actually
6:13
double backslash
in regex to escape a character.
6:15
Check the teacher's notes below
to learn more about split and regex.
6:19
So let's just go
6:24
ahead and we'll call the add song method
that exists.
6:25
We'll make a brand new song
with these args.
6:28
So again, just above,
it's the artist, the title, and the URL.
6:31
And those are the parameters
to the constructor for the new song.
6:36
So we'll plug in each arg in order.
6:40
So we're going to loop through each line
and add a song
6:42
for each one,
creating that new song in the process.
6:45
Cool, right?
6:48
And we'll do a very similar thing
6:54
as above in our catch.
6:56
Problems loading %s
7:02
and that's the file name there
7:09
and let's just go ahead
and give them a stack trace as well
7:11
so they can see the problem. Cool, alright
7:14
and because we're in songbook
I don't think
7:20
we've imported these things in here
so let's go ahead and do that
7:22
I'll just do the lazy version again
if you want to
7:26
you can write all those out I'm going
to do the lazy version of java.io.star
7:28
So we could add to the menu to load
and save the file,
7:35
but we can also make sure
7:38
that every time the application started
that we would load it.
7:39
And every time that we quit, we saved it.
7:43
So anything that added would be there.
Let's do just that.
7:45
Let's go back over
to our original karaoke file here
7:49
and let's call songbook.import from
7:52
songs.txt.
7:57
And remember that's relative
to where the program's running from
7:59
for that file.
8:03
So the first time it goes,
it's going to blow up
8:04
because there's not a songs.txt.
8:07
So let's just put a little message here
so we can see it.
8:09
System.out.println saving book.
8:12
Then let's do
8:20
songbook.export to songs.txt.
8:21
Cool, we'll save that.
8:26
Now anytime
that programming ends successfully,
8:30
the data will be saved and on restart
it will be loaded back.
8:32
Let's run that and make sure
that it's working as we think it is.
8:36
There we go!
8:45
So this first error here is
actually the error that we were expecting.
8:46
The songs.txt wasn't there, so it tried
to read the file and it wasn't there.
8:51
So let's go ahead and we'll add one.
8:56
Also, I'm sorry
8:59
if you're watching this with subtitles
and they're blocking my text down here,
8:59
but because we're running this program,
I can't do the typical Ctrl-L
9:03
to clear it back to the top.
9:07
But you can actually click and drag
those subtitles around to a
9:09
different part of the screen.
9:11
Okay, let's add MJ back in here.
9:13
And we'll put Beat It.
9:19
And finally this link here.
9:22
Awesome.
9:26
So there's one song.
9:26
Let's go ahead and say Quit.
9:28
And now it says Saving Book.
9:30
And if we look over here,
if we right click, we refresh,
9:32
we'll see that Songs.txt is here.
9:38
You can open it up and there it is.
9:42
So I have in my clipboard
a handful of popular songs for karaoke,
9:44
just for us to play around with
9:48
and to make sure our program's
working the way that we want it to.
9:50
It's down in the teacher's notes for you
to copy, and let's paste those in here.
9:53
Cool, so now let's go use it a bit, now
that we have some actual data in there.
9:59
Cool, there's
10:13
15 songs available, that is awesome.
10:14
And let's go ahead and let's choose
a song to sing.
10:17
Hmm, those are out of order, aren't they?
10:20
Well let's look and see
what's going on in the Jackson 5.
10:23
Those songs are out of order too.
10:28
We can fix that pretty quick.
10:30
Let's go do that.
10:32
So I'm going to quit with Control C
and clear
10:33
with Control L.
10:36
okay so first things first
that list of artists needs to be sorted
10:40
alphabetically
so let's go change that by artist map
10:45
so if we come into the songbook
and we go into where this by artist
10:49
map was we can change the implementation
from a hash map
10:52
to a tree map
10:55
and bam
10:59
just that
that's all the code we needed to change
10:59
well that and the fact that we need
to change our import So instead of a hash
11:03
map here, we're going to say tree map
and keep it in alphabetical order.
11:06
Nice.
11:15
And we also
saw that the song order was out of whack.
11:17
Okay, so let's go take a look down here
at the get songs by artists that we have.
11:19
Okay, so let's pull this out
11:25
into a variable.
11:27
So we'll say that this is a list of songs.
11:30
We'll call it songs.
11:33
And now,
lists can be sorted with the sort method,
11:36
and that sort method takes a parameter
that implements a comparator interface
11:39
Now I want to show you a cool trick
that you gonna start seeing quite a bit of
11:44
It called an anonymous inline class
and it looks a little weird
11:48
so hold on tight So songs.sort,
11:52
but we're going to say new comparator,
11:57
which is an interface of songs.
11:59
And then we're going to
start defining a class body.
12:03
and I know that this looks very weird
12:08
but see how I have a code block
that's open here
12:10
so what you do in here is you write
whatever you want to do
12:13
comparators have a compare method
which is very similar to the compare
12:16
to method and we're going to override that
12:20
it takes
12:27
two of the items
so we have song one and song
12:28
two and automatically
those are going to get pushed into there.
12:32
So to compare here, we'll use this code.
12:36
But yeah, it's a little weird, right?
12:38
This is an interface,
but we're making a new version.
12:40
And we're implementing
the one required method, which is compare.
12:43
And again, I'm marking it with override.
12:47
And so this is just the compare to method
that we had before.
12:49
So again, the rules are if they're equal
to each other, you return 0.
12:53
Otherwise,
let's just return the titles, right?
13:00
Return the song1.mtitle.compareTo
13:03
song2.mtitle. Ugh,
13:06
just thought of something.
13:15
That mtitle field is private.
13:16
Before
we were able to do some sort of sorting
13:18
when we were in the same class,
but now we're not in the same class.
13:21
We're in Songbook. We're not in Song.java.
13:24
So there's a little trick
to handle this as well.
13:27
So in Song.java, if you change this word,
which you've probably seen
13:29
in your Java journeys,
from private to protected, what
13:34
that means is anything in this package
can access this, okay?
13:37
And that's exactly what we want, right?
13:42
We want to have the Songbook
13:44
class access these variables
that are in the Song class,
13:45
and they're in the same package,
so we use protected.
13:48
Cool?
13:51
so again this is making a new interface
13:53
this is an anonymous class and
it will implement the comparable interface
13:56
if they're equal it'll return zero
14:00
otherwise it will sort by the title
okay let's make sure both files are saved
14:03
and let's see how we're doing
14:07
oh whoops
14:14
gotta import comparator in songbook okay
so let's go into the top of songbook here
14:15
we will import comparator
and that's in java.util
14:21
let's try that again
14:31
oh the errors the errors
well at least you're getting
14:40
some good practice on reading errors.
No one is perfect.
14:44
missing return statement
14:48
so I forgot
14:55
we need to actually return a list of songs
from this method it was there before
14:56
but I changed it to a variable so
after the sort we're going to return songs
15:00
all right one more time here we go
15:07
fingers crossed that we got it
15:09
Okay, so there's 15 songs available.
15:15
Let's choose.
15:17
Awesome.
15:19
We got it in the right order there for it.
15:20
That's alphabetical order
just by using that tree map.
15:22
And if we go into one of these artists,
I want to look up Jackson 5 again.
15:25
All the songs here are in alphabetical
order too.
15:29
Awesome. We did it.
15:32
Artists are sorted. Songs are sorted.
15:34
And we are all done with that story,
which finishes the sprint.
15:36
We did it.
15:40
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up