The words you are searching are inside this book. To get more targeted content, please make full-text search by clicking here.
Discover the best professional documents and content resources in AnyFlip Document Base.
Search
Published by , 2018-04-08 11:57:54

head-first-java-2nd-edition

head-first-java-2nd-edition

serialization and file I/O

Pata lMoves itt streatMs frotM ot1e place to at1other.

CO"t1ectio"
strealMs represe)tt

a eOt1t1ectlot1
toa source or
destlt1aflot1 (file,

-socket etc.) while

chal" streatMs
cat1't oot1"ecf Ot1
their OW" 3"d tMust
be chal"ed toa
cot1t1ectfo" dna",.

The java I/O API has amnection streams, that represent connections to destinations and
sources such as files or network sockets, and chain streams that work only if chained to
other streams.

Often, it takes at least two streams hooked together to do something useful-one to
represent the connection and anotherto call methods on. \\Thy two? Because connection
streams are usually too low-level. FileOutputStream (a connection stream), for example,
has methods for writing byles. But we don 't want to write byusl We want to write objects, so
we need a higher-level chain stream.

OK, then why not have just a single stream that does exactly what you want? One that lets
you write objects but underneath converts them to bytes? Think good 00. Each class
does onething well. File OurpurStreams write bytes to a file. ObjectOurputStreams turn
objects into data that can be written to a stream. So we make a FileOutputStream that lets
us write to a file, and we hook an ObjectOutputStrearn (a chain stream) on the end of it.
When we call writeObject() on the ObjectOutputStream. the object gets pumped into the
stream and then moves to the FileOutputStream where it ultimately gets written as bytes
to a file.

The ability to mix and match different combinations of connection and chain streams
gives you tremendous flexibilityl If you were forced to use only a singlestream class, you'd
be at the mercy of the API designers. hoping they'd thought of everythitlgyou might ever
want to do. But with chaining, you can patch together your own custom chains.

object is flattened (serialized) object is written as bytes to 01101001
01101110
is written to 011010010110111001 01
is chained to

ObjectOutputStreom Fil e O u t p u t S t r e a m File
(a choin stream) (a connection stream) you are he re ~ 433

serialized objects

What really happens to a., object
whet' itl serialized?

o Object on the heap G Object serialized

Objects on the. heap have state-the Serialized objects save the values
value of the object's instance of the instance variables. so that
variables. These values make one an identical instance (object) can be
instance of a class different from brought back to life on the heap.
another instance of the same class.
00100101

01000110

Foo myFoo = new Foo();
myFoo .setwidth(37);
myFoo.setBeight(70);

434 chapter 14

serlallzatlon and file I/O

-'ut what exactly IS att object~ state?

What needs to be saved?

Now it starts to get interesting. Easy enough to save the primitive
values 37 and 70. But what if an obj ect has an instance variable
that's an object reference? What about an object that has five
instance variables that are object references? What if those object
instance variables themselves have instance variables?

Think about it. What part of an object is potentially unique?
Imagine what needs to be restored in order to get an object that's
identical to the one that was saved . It will have a different memory
location. of course. but we don't care about that, All we care about
is that out there on the heap. we'll get an object that has the same
state the object had when it was saved .

Vi!iiJlj1 Iraill Barbell

What has to happen for the Car The Car object has two
Instance variables that
object to be saved in such a way reference two other
that It can be restored back to its objects.
original state?

Think of what-and how-you
might need to save the Car.

And what happens ifan Engine
object has a reference to a
Carburator7 And what's inside the

nre 0 array object?

What doe8 It take to
save a Car object?

you are here. 435

serialized objects Serialization saves the

When an object is serialized, all the objects entire object grapb..
it refers to from Instance variables are also
serialized. And all the objects those objects All objects reterenced
refer to are serialized. And all the objects those by instance variables,
objects refer to are serialized••• and the best
part is, it happens automaticallyl starting with the

This Kennel object has a reference to a Dog [] array object. The object being serialized.
Dog [] holds references to two Dog objects. Each Dog object holds
a reference to a String and a Collar object. The String objects
have a collection of characters and the Collar objects have an into

When you save the Kennel, all of this ;s savedl

~-

~/\9[ ) arrcri o'o·~l:-

436 chapter 14

serialization and file 110

If you want your class to be serializable,
itMpletMet1t Serializable

The Serializable interface is known as a marker-or tag interface,

because the interface doesn't have any methods to implement. Its

sole purpose is to announce that the class implementing it is, well,

serializable. In other words, objects of that type are saveable through

the serialization mechanism. Ifany superclass of a class is serializable,

the subclass is automatically serializable even if the subclass doesn't

explicitly declare implements Serializable. (This is how interfaces always

work. If your superclass "IS-A" Serializable, you are too). MIASI i",y\c",e'llt.
'neYc
~ ~Sey\~a"\'e\hY~\OC;,ott:.sJ( it. ...i\\ r '\ t. Yu.f\t.i",c,
objectOUtputStream. wri teObject (myBox) ; -tal a

~'~\)\t , ' lhc ' a'la,io yat.\l.aO;,C. so

~ , 'S iI"'l"l'"y~',)

import java. io. *; SeYli e..d t.'nt
'1011' 'II ..

public class Box implements Serializable

......... ~ ../

public void setWidth (int w)

width = w;

public void setHeight(int h}

height = h;

public static void main (String[] args) { ))

= d \\~oo,seY
Box myBox new Box() ; l to i ~~i'\ItC. YId.,.,.C I t. ¥.e a
myBox.setWidth(50}; dot.s,", ",i
myBox.setHeight(20); COY\'IItt." .
~ei'J\l.tIstYsI·d"\'cd
10 ovtV'abo"s t.a" "lnLYO'" euer..-.l.io\llS.! i"rl' .It. \\~oo·seY".
I "c'"
~ 1

try {
=FileoutputStream fs new FileOUtputStream("foo.ser") ;
=ObjectOUtputStream os new ObjectOUtputStream(fs);
~ Make ah Ob'etto
os.writeObject(myBox);
os. close () ; ......... thaihed to :J "tp"tstrea",

catch (Exception ex) { the tOhhettioh st
ex.printSt&ckTrace(); Tell it to W\-'te 1
rea""
I l::he objett.

you are here. 437

serialized objects

Serialization is all or nothing. Eeewww! That
creeps me out just thinking
Can you imagine what would
happen If some of the object's about itl Like, what if a Dog comes
state didn't save correctly?
back with rIO weight. Or no ears. Or
the collar comes back size 3 instead
of 30 . That just can't be allowedl

Either the entire
object graph is
serialized correctly
or serialization fails.

You can't serialize

a Pond object if

import java.io .*; its Duck instance
variable refuses to
~ POI'IO obj~eL ea" b~ so-ializ..ed. be senallzed (by
not implementing
public class Pond implements Serializable ( Seriafizable).

= CvaI~ai",a..blPeO, l'lad Dhas ont 'IN taTlee
Ie.
private Duck duck new Duck(); ~

vl. ,

public static void llIain (Strinq[] arqs) {

=Pond myPond new Pond();

try (
FileOutputstreAm fs : new FileOUtputStream( "Pond.'ser");

ObjectOUtputStream os : new ObjeotOutputStream (fs) ;

. ..,e--. Wh. bl.yo.. so-ia'i~ ""yPond ( P

os . wr i t e Ob ) 8 c t (myPo n d ) ;

os . close () ; obJuV, ih Dlotk i>\lU a ol'ld
aui:o-....a ti t...i II ser.lIa'Il~~l~vda. riable
catch(Exception ex) ( y 3c1't.--\ PO'PIO:
ex .printStackTrace() ; to YWI ~t .
",ai" dass
I"

438 ch ap ter 14

serialization and file 110

It's hopeless,
then? I'm completely
screwed if the idiot who
wrote the class for my instance
variable forgot to make it

Serializable?

Mark an Instance variable as transient

If It can't (or shouldn't) be saved. -

If you want an instance variable to be skipped by the
serialization process, mark the variable with the transient
keyword.

. • ~ import java.net.*:
class Chat implements Serializable {
t !o4i'r' "Otil'C.
b-a.,.s~~iS ~aV"\a'o\tl O~~Il\~t.)I~
s~aV""ita\vi-z'.a.bO"f\,~'I>S~ n.'" transient Strinq currentID;

J ---

~ Strinq userNamej

lI..SC'rNa....e variable / / more code
ow.ifll~bte. saved as pari }
obJt.d:'s st.dte

dUY"'9 st.\"laliz.aiiol'l.

lfyou have an instance variable that can't be saved because 439
it isn't serializable, you can mark that variable with the
transient keyword and the serialization process will skip right
over it.

So why would a variable not be serializable? It could be

that the class designer simply /ClTgot to make the class

implement Serializable, Or it might be because the object
relies on runtime-specific information that simply can't be
saved. Although most things in the java class libraries are
serializable, you can't save things like network connections,
threads, or file objects. They're all dependent on (and
specific to) a particular runtime 'experience'. In other words,
they're instantiated in a way that's unique to a particular run
of yoor program, on a particular platform, in a particular

JVM. Once the program shuts down, there's no way to bring

those things back to life in any meaningful way; they have to
be created from scratch each time.

you are here ~

serialized objects

DUthmereblm~-~u?est19n8

Q: If serialization is so important, A: Yes! If the class itself is as null, regardless of the value it had
at the time it was saved.That means
why isn't it the default for all classes? extendable (i.e. not final), you can the entire object graph connected to
Why doesn't class Object implement make a serializable subclass,and just that particular instance variable won't
Serializable, and then all subclasses substitute the subclass everywhere be saved.This could be bad, obviously,
will be automatically Serializable. your code is expecting the superclass because you probably need a non-null
type. (Remember, polymorphism value for that variable.
A: Even though most classeswill, allows this.) Which brings up another
interesting issue: what does it mean if You have two options:
and should, implement Serializable, the superclass is not serializable?
you always have a choice. And you 1) When the object is brought back,
must make a conscious decision on Q: You brought it up: what does it reinitialize that null instance variable
a c1ass-by-c1ass basis,for each class back to some default state. This
you design, to 'enable' serialization mean to have a serializable subclass works if your deserialized object isn't
by implementing Serializable. of a non-serializable superclass? dependent on a particular value for
First of all, if serialization were the that transient variable. In other words,
default, how would you turn it off? A: First we have to look at what it might be important that the Dog
Interfaces indicate functionality, not have a Collar, but perhaps all Collar
a lack of functionality, so the model happens when a class is deserialized, objects are the same so it doesn't
of polymorphism wouldn't work (we'll talk-about that on the next few matter if you give the resurrected Dog
correctly if you had to say/implements pages). In a nutshell, when an object a brand new Collar; nobody will know
NonSerializable"to tell the world that is deserialized and its superclass is not the difference.
you cannot be saved. serializable, the superclass constructor
will run just as though a new object of 2) If the value of the transient variable
Q: Why would I ever write a class that type were being created. If there's does matter (say, if the color and design
no decent reason for a class to not of the transient Collar are unique for
that wasn't serializable? be serializable, making a serializable each Dog) then you need to save the
subclass might be a good solution. key values of the Collar and use them
A: There are very few reasons, but when the Dog is brought back to
Q: Whoall just realized essentially re-create a brand new Collar
you might, for example, have a security that's identical to the original.
issue where you don't want a password something big •••if you make a
object stored. Or you might have an variable 'transient~this means the Q: What happens if two objects in
object that makes no sense to save, variable's value is skipped over
because its key instance variables are during serialization. Then what the object graph are the same object?
themselves not serializable, so there's happens to it? We solve the problem Like, if you have two different Cat
no useful way for you to make your of having a non-serializable instance objects in the Kennel, but both Cats
class serializable. variable by making the instance have a reference to the same Owner
variable transient, but don't we NEED object. Does the Owner get saved
Q: If a class I'm using isn't that variable when the object is twice? I'm hoping not.

serializable, but there's no good brought back to life? In other words, A: Excellent question! Serialization
reason (except that the designer just
forgot or was stupid), can I subclass isn't the whole point of serialization is smart enough to know when two
to preserve an object's state? objects in the graph are the same.In
the 'bad' class and make the subclass that case,only one of the objects is
A: Yes, this is an issue,but saved,and during deserialization, any
serializable? references to that single object are
fortunately there's a solution. If you restored.
serialize an object, a transient reference
instance variable will be brought back

440 cha pte r 14

Peserializatiot1= restorit1Q att object serlallzatJon and file 1/0

The whole point of serializing an object is so that you can serializ.ed
restore it back to its original state at some later date, in a
different 'run' of theJVM (which might not even be the same J,.

JVM that was running at the time the object was serialized).

Deserialization is a lot like serialization in reverse.

o Make a FilelnputStreQtn
FilelnputStream fileStream = new

e ~ the objects

Object one = os.readObject();
Object two = os.readObject();
Object three = os.readObject();

e -cast the objects

you are here, 441

deserlallzlng objects

What happe.,s durhtg deserializatio.,?

When an object is deserialized, thejVM attempts to bring

the object back to life by making a new object on the heap

that has the same state the serialized object had at the time it ~e

was serialized. Well, except for the transient variables, which eCJW:· I~. r JVM
come back either null (for object references) or as default dass.
primitive values. \his stty .\\ ~\'(O-d.l~eell'
-.II
- :t ~\"d'" ea

01101001 object is read as bytes class is found and loaded, saved
instance variables reassigned
01101110 __----~ 011010010110111001 Object
01 is read by is chained to
ObjectInputStream
File FiJeInputStream (a chain stream)
(0 connection stream)

o The object is read from the stream.

e The JVM determines (through info stored with

the serialized object) the object's class type.

The JVM attempts t? find and load the ob-

ject's class. If the JVM can't find and/or load
the class, the JVM throws an exception and
the deserialization fails .

A new object is given space on the heap, but
the serIalized obJeds constructor does
NOT runl Obviously, if the constructor ran, it
would restore the state of the object back
to its original 'new' state, and that's not what
we wont. We want the object to be restored
to the state it had when it was serialized, not
when it was first created.

442 chapter 14

serialization and file I/O

G If the object has a non-serializable class

somewhere up its inheritance tree, the
constructor for that non-serializable class
will run along with any constructors above
that (even if they're serializable). Once the
constructor chaining begins, you can't stop it,
which means all superclasses, beginning with
the first non-serializable one, will reinitialize
their state.

CD The object's instance variables are given the

values from the serialized state. Transient
variables are given a value of null for object
references and defaults (0, false , etc.) for
primitives.

D:Ut1emre1blU'H~u?estl0 9n8 argument, and if the JVM receiving the call doesn't have
the class,it can use the URl to fetch the class from the
Q:Whydoesn't the class get saved as part of the ob" network and load it, all automatically. (We'll talk about RMI
in chapter 17.)
ject? That way you don't have the problem with whether

the class can be found.

A: Sure,they could have made serialization work that Q:What about static variables? Are they serialized?

way. But what a tremendous waste and overhead. And A: Nope. Remember, static means "one per class"not
while it might not be such a hardship when you're using
serialization to write objects to a file on a local hard drive, "one per object" Static variables are not saved, and when an
serialization is also used to send objects over a network object is deserialized, it will have whatever static variable
connection. If a class was bundled with each serialized
(shippable) object, bandwidth would become a much larger its class currentlyhas.The moral : don't make serializable ob-
problem than it already is.
jects dependent on a dynamically-changing static variable!
For objects serialized to ship over a network, though, there It might not be the same when the object comes back.

actually is a mechanism where the serialized object can be

'stamped' with a URl for where its class can be found. This
is used in Java's Remote Method Invocation (RMI) so that
you can send a serialized object as part of, say, a method

you are here ~ 443

serialization example

Savit1g at1d restorit1g the gattte characters

import java.io.*;

public class GameSaverTest { Make sow-t tna~atte'rt-· ·

public static void main(String(] axgs} {

GameCharacter one = new GameCharacter(50, "Elf" , new Strinq{] ("bow", "sword", "dust"});

=GameCharacter two new GameCha.racter (200, "Troll", new String! 1 {"bare hands" J "big ax"}) ;
=GameCharacter three new GameCharacter(120, "Magician", new String[l ("spells", "invisibility"}) ;

/ / imagine code that does things with the characters that might change their state values

try {

ObjectOutputStream 09 =new ObjectOutputstream (new Fileoutputstream ("Game. ser") ) ;

os.writeObject(one) ;

os.writeQbject(two) ;

os.writeQbject(three) i

os. close () ;

catch(IOExceptioD ex) (

ex.printStackTrace() ;

} Wt stt tnt... tD ""II so '\lit un't

one = null;
two = null; ~ alUSS t.ht objttts 0l'I -\:he ht.af·
=three null;

Now \'"tad tht... balK j" +\'"0'" the tilt...

~{ ~

Objectlnputstream is = new Objectlnputstream(new Filelnputstream ("Game. ser")) ;

Gamecharacter oneRestore = (GameCharacter) is. readObject () ;
GameCharacter twoRestore = (GameCharacter) is. readObject () ;
=GameCharacter threeRestore (GameCharacter) is. readObject () ;

System. out. println ("One' B type : \I + oneRestore. g8tType () ) ; ~ Chtt'tt. -to see ~ .t. oVlt.t4·
Systern.au t .println ("Two's type : " + twoRestore. getType () ) ;
i \ ....

System.out.println("Three's type: " + threeRestore .getTypeO) j

catch(Exception ex) (

ex .printstackTrace();

444 ch apter 14

serialization and file 110

fhe G-atl1eCharacfer class

import java.io. t ;

public class GameCharacter implements Serializable {
int power;
String type;
String[] weapons;

public GameCharacter(int p, String t, String[] w) {

power =p;
wtyepaepo=nst=; w;

public int getPower ()
return power;

public String getType()
return type;

public String getWeapons () {
String weaponList = "":

for (int i =0; i < weapons. length; iff) {

weaponList += weapons[i] + " ";

}

return weaponList;

you are here " 445

saving objects

Ol.jed Serialization

)- You can save an objecfs state byserializJng the object.

)- To serialize an object, you need an ObJectOutputStream (from the
java.lo package)

)- Streams are either connection streams orchain streams

.. Connection streams can represent a connection toa source or
destination, typically afile, network socket connection, orthe
console.

)- Chain streams cannot connect to a source ordestination and must

be chained to a connection (or other) stream.
)- To serialize an object to a file, make a RleOuputStream and chain ~

into an ObjectOutputStream.

.. To serialize an object, call writeObject(theObject) on the

ObjectOutputStream. You do not need to call methods on the

FUeOutputSlream.

)- To be serialized. an object must Implement the Seriallzable interface.
Ita superclass ofthe class Implements Serializabls, the subclass will
automatically beseria\lzable even If ~ does not speclfically declare
implements Seri8/1zable.

)- When an object Isserialized, its entire oblect graph Isserialized. That
means any objects referenced bythe serialized object's instance
variables are serialized, and any objects referenced bythose
obJects...and soon.

• If any object in the graph Is not serializable, an exception will be
thrown at runlime, unless the Instance variable referring tothe object
Isskipped.

.. Marie aninstance variable with the transient keyword if you want
serialization to skip that variable. The variable will be restored as null
(for object references) ordefault values (for primitives).

. • During deseriallzation, the class ofallobjects Inthe graph must be
available tothe JVM.

• You read objects In (using readObjeet()) Inthe order In which they
were originally written.

• The retum type ofreadObjectO istype Object, so deserialized
objects must be cast to their real type.

• Static variables are not serializedI Itdoesn't make sense to save
a static variable value as part of a specific objecfs state. sInce all
objects of that type share only a single valu&-the one Inthe class.

446 chapter 14

Writi"g a Strittg to afext File serialization and file I/O

Saving objects, through serialization, is the easiest way to save and 60,Elf,how, sword,dust
restore data between runnings of a Java program. But sometimes you 200,Troll,ba.re ha.ndB,hlg ax
need to save data to a plain old text file. Imagine your Java program 120,Maglolan,spel1B,invisibillty
has to write data to a simple text file that some other (perhaps non-
Java) program needs to read. You might. for example, have a servlet
(Java code running within your web server) that takes form data the
user typed into a browser, and writes it to a text file that somebody else
loads into a spreadsheet for analysis .
Writing text data (a String, actually) is similar to writing an object,
except you write a String instead of an object. and you use a
FileWriter instead of a FileOurputStream (and you don't chain it to an
ObjectOutputStream) .

To write Q serialized object:
ObjQctOutputstream.vriteObject(someObject);

To write Q String:
fileWriter. wri te ("My first String to save") j

import

class WriteAFile {
public static void main (String[] args) {

try {

=FileWriter writer

d1'l\t\.'\.t\.:..I0.I.'-LJ$'2!-t'-.C.v,~t'Ill)-.v'It'r.~i~''\,y11-\''1b1/~0a0'/~1.b1•,\.s.-.b'>"(I~~t~....ao-'tuJ.~ ./ writer . write ("hello foo ! ") ; ~ Tht -.-iuO "'«hod uk
a St.ril'l~
es

writer. close () ; ~ Cl 'l-

aSt '"1:. ....hCtl YO\l.'rt dO"ll

) catch(IOException ex) (
ex.printStackTrace();

}

you are here ~ 447

writing a text file

fext File ExatMple; e-Flashcards

Remember those flashcards you used in school? Where you QulzCard
had a question on one side and the answer on the back?
They aren't much help when you 're trying to understand QuizCard(q, a)
something, but nothing bears 'em for raw drill-and-practice
question
and rote memorization. When JfYU have to burn in afaa. And
answer
they're also great for trivia games.

We're going to make an electronic version that has three
classes:

1) QuizCardBuilder. a simple authoring tool for creating and
saving a set of e-Flashcards,

2) QuizCardPlayer. a playback engine that can load a
flashcard set and play it for the user.

3) QuizCard, a simple class representing card data. We'll
walk through the code for the builder and the player, and
have you make the QuizCard class yourself, using this ~

gelQuestion 0

18 0e Qvlz CMd",lIdo, gelAnswerQ
Quu l lon:
FI.. I

Which university Is featured In the ,
film -Good Will Huntlng~
,

, ()I~ card" - ,
8 8e

~ f j"

I ,What happens If you call

I l:0bject.getPrimaryKeyO on a
sian bean's remote reference?
J
I
,,~ .. An. ...r:

M.I.T. ~ I~

,I ::

II , 10 LA)
i
-- - ( ShoW_, )

( Wulc.id )

-;

-~ "- ~

QulzCardBullder QulzCardPlayer

Has a File menu witk a ~SaveH option for saving Has a File menu with a "Load" option for loading a
the current set of cards to a text file. set of cards from a text fife.

448 chapter 14

serialization and file 110

Quiz Card 'uilder (code outli.,e)

public class QuizCardBuild er {

public void goO {
/ / build an d display gui

IMev- t.lass
private class NextCardListener implements ActionListener {

public void actionPerformed(Action Even t ev) {
/ / add the cu rr e nt card to the list and clear the text areas

IlIlIev- dass
private class SaveMenuListener imp lemen ts ActionListener {

public void action Performed (ActionEven t ev) {
/ / bring up a file dialog box
/ / let th e user name and save the set

IlIlIev- dass
p rivate class NewMenuListener implements ActionListener {

public void action Performed (ActionEven t ev) {

II d ear out the card list, and dear out the text areas

private void saveFIle(File file) {
/ / ite rate through the list of cards, and write each one ou t to a text file
/ / in a parseab le way (in oth e r words , with clear separations be tween parts)

Called by the Sa\leMell...L.istenev-;

does the at.hal ~ile WV"ibn~.

you are here ~ 449

Quiz Card Builder code

import java.util.*;
import Jj,aavvaa.xa.wswt ..mevq,e*n;t. *;
import
import jj.aavvaa . ai.wo .t *. * ;
import ;
i

public class QuizCardBuilder

private JTextArea questi on;
private JTextArea answer;
private ArrayList<QuizCard> car dLi s t ;
private JFrame frame;

public static void main (String!] ar gs ) {
QuizCardBuilder builder = new QuizCardBuilder();
builder. go () ;

public void got) {
/ / build gui

f rame = new JFrame(uQuiz Card Builder");
JPanel mainPanel = new JPanel();

Font bigFont = new Font(Usanserif", Font.BOLD, 24);
question = new JTextArea(6,20);
question.setLineWrap(true);
question.setWrapStyleWord(true);
question.setFont(bigFont);

JScrollPane qScroller = new J Scro l l Pane (ques t i on) ;
qScroller .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL SCROLLBAR ALWAYS);
qScroller .setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

answer = new JTextArea(6, 20);
answer.setLineWrap(true);
answer.setWrapStyleWord(true);
answer.setFont(bigFont);

JScrollPane aScroller = new JScrollPane(answer);
aScroller. setVerticalScrollBarPolicy (Scr ollPaneConstants.VERTICAL SCROLLBAR ALWAYS);
aScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

JButton nextButton = new JButton(UNext Card");

cardList = new ArrayL ist<QuizCard>();

JLabel qLabel = new JLabel(uQuestion:" );
JLabel aLabel = new JLabel(UAnswer:");

mainPanel.add(qLabel);
mainPanel.add(qScroller);
mainPanel.add(aLabel);
mainPanel.add(aScroller);
mainPanel.add(nextButton);
nextButton.addActionListener(new NextCardListener());

JMenuBar menuBar = new JMenuBar();

JMenu fileMenu = new JMenu(UFile");

JMenultem newMenultem = new JMenultem( UNew");

450 chapter 14

serialization and file I/O

JMenultem saveMenultem = new JMenultem("SaveH)i

newMenultem.addActionListener(new NewMenuListener());
saveMenultem.addActionListener(new SaveMenuListener());
tileMenu.add(newMenultem)i
fileMenu.add(saveMenultem)i
menuBar.add(fileMenu);
frame.setJMenuBar(menuBarli
frame.getContentPane() . add (BorderLayout. CENTER,
frame.setSize(500,600) i
frame.setVisible(true)i

public class NextCardListener implements ActionListener (
public void actionPerformed(ActionEvent ev) (

QuizCard card = new QuizCard(question.getText(), answer.getText());

cardList.add(card) i
clearCard ();

public class SaveHenuListener implements ActionLiatener (
public void actionPerformed(ActionEvent ev) (
QuizCard card = new QuizCard(question.getText(), answer .getText());
cardList .add(card); ~a\~i\\~e tdMiat.\M~~i\o\e)S<VId...i..'1as\r.:-a1d~re'.Oo~It'aY1-.\1b~'0O1B>"O'C'0'I',f'l1\\;~t.bean'>I~Sej

0=;:.._ - 'O-ri. . ~~
\i...e
W'lB\
d'Id\~ bo'1- r. ~ 'IS aOfle o>r
public class NewManuListener implements ActiOnListen~sfe\\~'t\.bfCl\e>~a!...,\eIlt.~ed\\'1 is HilS dS'f'
public void actionPerformed(ActionEvent ev) (
cardList.clear(li
clearCard () i

private void clearCard() ( c>:

question.setText("")j
answer.setText(KHl j
question,requestFocuS()i

private void saveFile(File file) / e:-:

try {
BufferedWriter writer ~ new BufferedWriter(new FileWriter(file))i )

for (QuizCard card: cardList) (

ijwriter.write/card.getQuestion() + ... i")

i-writer, write (card.getAnswer () + "'\n") j

< .wIriter.close/);
~l! t.h.ai" d B~.f(l-edW\"ik
FJleWI"'ite-- to IR,)lce 't; "~fIO-t! etoeHai'tlieew"f..
(We11 i:.llk abow! th a ''I d 1'ew fa~e.v .

catch (IOException ex) { a.f~sWd(~rldt-ad\l".laelis~llCItapI,hrtd.Wdwrr/.i'~lL~aWIhlltu"td=i1ht.~.habterytdJQ,at\Ale.otr.et"S.r/-.'"-"ba~O,y"(ttL"a!,\'n1'aO1d~"d"n)i0.eh>+.tb.,d,lr-d
System .out.println("couldn't write the cardList out");
ex. pr!ntStackTrace () i

you are here. 451

writing fIles A File object represents the name

fhe java.ioJiIeclass and path of a file or directory on

The java.io.File class represents a file on disk, but doesn't disk, for example:
actually represent the contents of the file. What? Think of
a File object as something more like a pat/manu of a file JUsersJKathy/DataJGameFile.txt
(or even a directory) rather than The Actual File Itself.
The File class does not, for example. have methods for But it does NOT represent, or give
reading and writing. One VERY useful thing about a File you access to, the data in the filel
object is that it offers a much safer way to represent a
file than just using a String file name . For example. most
classes that take a String file name in their constructor
(like FileWriter or FileInputStream) can take a File
object instead. You can construct a File object, verify
that you've got a valid path, etc. and then give that File
object to the FileWriter or FilelnputStream.

Some things you can do with B File object:

. . Make a File object repr~ntlng an
existing tHe

=File f new File(~MyCode.txtUI j

@ Make Q new directory

File dir =new File("Chapter7n l ;

dir .mkdir () ;

• List the contents of a directory

if (dir.isDirectory()I {

String [1 di ir=Co0n; tien<tsd=irCdiorn.tleinstts(.)le;ngth; iH) {
for (int

System.out.println(dirContents[i]);

8) Get the absolute path of Q file or directory
System.out.println(dir .getAbsolutePath(»;

I) Delete a file or directory (returns true If
successful)

boolean isDeleted =f.delete()j

452 chapte r 14

serialization and file 1/0

The beauty of buffers

If there were no buffers, It would be like
shopping without a cart. You'd have to
carry each thing out to your car. one soup
can or toilet paper roll at a time.

String is put into a buffer When the buffer ;s full. the Aspen
with other Strings Strings are all written to Denver
Boulder
"Boulder" ,... "BoulderH U~eD" •Aspen Denver BoulderM
is written to "Denver" is chained to File
FlleWrlter
String BufferedWrlter (a connection stream
that writes characters
(a chain stream that as opposed to bytes)

works with characters)

=BufferedNriter writer new BufferedKriter(new FileWriter(aFile))i

~

The cool thing about buffers is that they're much. more efficient than
working without them . You can write to a file using FileWriter alone, by
calling write (someString) , but FileWriter writes each and every thing you
pass to the file each and every time. That's overhead you don't want or
need. since every trip to the disk is a Big Deal compared to manipulating
data in memory. By chaining a BufferedWriter onto a FileWriter, the
BufferedWriter will hold all the stuff you write to it until it's full. Only when
the buffer isfull will theFUe Writeractually be told to unite to thefile on disk.

If you do want to send data beftn» the buffer is full, you do have control.

Just Flush It. Calls La writer.flush () say. "send whatever's in the buffer, now!h

you are here) 453

reading files What's 2 + 2?/4
What's 20+22/42
Readittg frotH a fext File

Reading text from a file is simple, but this time we'll use a File
object to represent the file, a FileReader to do the actual reading,
and a BufferedReader to make the reading more efficient.

The read happens by reading lines in a while loop, ending the loop
when the result of a readl.inej) is null. That's the most common
style for reading data (pretty much anything that's not a Serialized
object): read stuff in a while loop (actually a while loop tesf),
terminating when there's nothing left to read (which we know
because the result of whatever read method we're using is null) .

import java. io.~* ; DO'I'II t ~dr~dthti"""~ MyText.txt

class ReadAFile {

pub1ic static void main (Strinq(J arqs) { ( AthaFyialdtb(ead, tVLy'1~ata(f..Octrn.,~nUttots·otro, :.oa.uLU-e.al.I...ti,.".foilrt

try {
File myFile = new File("MyText .txt");
FileReader fileReader = new FileReader(myFile);

BufferedReader reader =

Makt a s.b-'Il'~ "a'(.l"'b.It t.o Ini old
. tl-lt linc IS yea
t4t.I-I Il't\t as '\,

String line = null;

while «line = reader.readLine(» != null) (
System. out.println (line) ;

}

reader.close();

catch(Exception ex) {
ex.printStackTrace();

454 chapter 14

serialization and file 1/0

Quiz Card Player (code outli"e)

public class QuizCardPlayer {

public void goO {
/ / build and display gui

class NextCardlistener implements ActionListener (
public void actionPerformed(ActionEvent ev) {
/ / if this is a question, show the answer, otherwise sh ow next question
/ / set a flag for whether we 're viewing a qu estio n or answer
}

}

class OpenMenuListener implemen ts ActionListener {
public void actionPerformed(ActionEvent ev) {
/ / bring up a file di alog box
/ / let the user navigate to an d choose a card se t to open

private void loadFile(File file) {
/ / must bu ild an ArrayList of cards, by reading them fro m a text file
/ / called from the OpenMenuListen er event h andler, reads the file one lin e at a time
/ / and tells the makeCard f) meth od to make a new card out of th e line

/ / (one line in th e file h olds bo th the question an d an swer, sep arated by a "I")

private void makeCard(String lineToParse) {
/ / calle d by th e Ioadf'ile method, ta kes a lin e fro m th e text file
/ / and parses into two pieces-s-qu estion and ans wer-a nd creates a new Q uizCard
/ / and adds it to th e ArrayList called CardList

you are here ~ 455

Quiz Card Player code

import java .util. *;
import java .awt. event.*;
import j avax . swi ng . *;
import java.awt. *;
import J. aVa. 1' 0 . * ;

public cl ass QuizCardPlayer

private JTextArea display;
pr i vate JTextArea answer;
private Arr ayLi s t <QuizCard> car dLi s t;
privat e QuizCard currentCard;
privat e int cur r ent Car dI ndex;
private JFrame frame;
privat e JBut ton nextButton;
private boolean isShowAnswer;

public static voi d main (String [] args) (
QuizCar dPl ayer r ea der = new QuizCardPlayer();
reader.go();

publi c void go()

II build gui

frame = new J Frame ("Quiz Card Player");
JPanel mainPanel = new JPanel();

Font bigFont = new Font("sanserif", Font.BOLD, 24);

display = new JTextA rea(lO, 20);
di splay. setFont (bigFont);

display. setLineWrap(true);
display. setEditable(false);

J ScrollPane qScroller = new JScrollPane(display);
qScroller.setVerticalScr ollBarPolicy(ScrollPaneConstants.VERTICAL SCROLLBAR ALWAYS);
qScroller. setHor izontalScrollBarPolicy (ScrollPaneConstants.HORIZONTAL SCROLLBAR NEVER);
nextBut ton = new JButton("Show Ques t i on" ) ; --

ma i nPanel . add (qScro l l er ) ;

mainPane l.add(nextButton);
nextButton.addActionListener(new NextCardListener());

JMenuBar menuBar = new JMenuBar();

JMenu fileMenu = new JMenu("File");

JMenuItem loadMenuItem = new JMenurtem ("Load card set");
l oadMenultem.addActionListener(new OpenMenuListener());
fileMenu. add (loadMenuItem) ;
menuBar .add (fil eMenu ) ;
f r ame.setJMenuBar(menuBar);
frame.getC ontentPane( ) .add(BorderLayout.CENTER, mainPanel);
frame.setSi ze( 640, 500);
frame. setVis ible(true) ;

II close go

456 chapter 14

serialization and file 110

public class NextcardListaner implements ActionListener (
public void actionperformed(ActionEvent eu) (
if (isShowAnswer) (
I I show the answer because they've seen the question
display.setText(currentCard .getAnswer(») ;
nextButton.setText(~Next Card");

isShowAnswer = false;

else {
II show the next question
if (currentCardIndex < cardList.size(»)
showNextCard();
else I
II there are no more cards!
wasdisplay.setText(~That last card");
nextButton .setEnabled(false);

public class OpenManuLiatanar implements ActionListener
public void actionPerformed(ActionEvent ev) (
JFileChooser fileOpen = new JFileChooser();

~ fileOpen.showOpenDialog(frame);

r 'loadFile(fileOpen .getSelectedFile(»:

)

~l

private void loadFile(File file) (

cardList = new ArrayList<QuizCard>();

try (
BufferedReader reader = new BufferedReader(new
String line = null:
while ((line = reader. readLine () I != null) (
makeCard(line) ;
I
reader.close();

catch(Exception ex) {
System. out. println ("couldn't read the card file") i
ex.printStackTrace();

I

II now t ime to start by showing the first card
showNextCard() ;
I

private void makeCUd(Stxing lineTOi'U88) ( ~I ~ E.fatl.h~hliuY..l.td: o.bflAUt.1'f\o.I-t:t ht.6.\o1ne-utoyoynadls"~to~• s-it,h,e~le
String () result = lineToParse . spli t (" I");
QuizCard card = new QuizCard(result{Oj, resu.l t l Ll j r Iot:S'ti ~ d al\S'W£\'" as stf.lYab: yiet.e1, We
cardList. add (card) ; ~~ SU~",I~ l'tO tthoa to b...eak +.he
System. out i prInt Ln ("made a card") j t Otl L st.i
IiI\( s.? I ... r.1 '\\Iot 071
he VIe
i'llto t'folO tokC'llS (oM. .,-«
arod 0YIe .t« -the .1\1"",£\'"), We'll look at tht:
~\itO ...dhod Of! the Ylt:1\.-t y,,~t,
privacteurvreonidtCsahrdow=NceaxrtdCLairsdtO.ge ( en tC ardln de x);
currentCardIndex++; t(curr

display .setText(currentCard.getQuestion();
nextButton .setText("Show Answer");
isShowAnswer = true;

}

I I close class

you are here ~ 457

parsing Strings with splitO Saved In a question file like this:

Parsittg with Strhtg splitCJ WhB.t is blue + yellow?j green
Wha.t 1B red + blue?jpurple
Imagine you have a flashcard like this:

What is blue + yellow? clJ\S'fie\"

green

How do you separate the question and answer?
When you read the file, the question and answer are smooshed

rtogether in one line, separated by a forward slash" (because

that's how we wrote the file in the QuizCardBuilder code).

String splitO lets you break a String Into pieces.
The spJitO method says, "give me a separator, and I'll break out ell
the pieces of this String for you and put them in 0 String array:

token 1 separator

468 chapter 14

serialization and file 1/0

Q:OK,I look In the API and there are about five Make it. St.itk

mUllon classes In the Java.lo package. How the heck do

you know which ones to use?

A..: The I/O API uses the modular 'chaining' concept so Roses arefirst, violetsare next. ext

that you can hook together connection streams and chain Redders and w,lters areonly for t .
streams (also called 'filter' streams) In a wide range of
• To wrile a text file, start with a FileWriler
combi nations to get Just about anyth Ing you couId wa nt . connection stream.

The chaIns don't have to stop at two levels; you can hook • Chain \he FileWriter toa BufferedWriter for
multiple chain st reams to one another to get just the right efficiency.
amount of processing you need.
• A File object represents a file ata particular
Most of the t ime, though, you'll use the same path, but does not represenl the actual
smaII handfu I of classes.If you're wrlti ng text flies, contents ofthe file.
BufferedReader and BufferedWriter (chained to FlIeReader
• With a File obiect you can create, traverse,
and Fll eWriter) are pro bably all you need. If you're wrlti ng
and delete directories.
serialized objects, you can use ObJeetOutputStream and
ObJectlnputStream (chained to FllelnputStream and • Mosl streams that can use a String filename
FileOutputStream). can use a File object as well, and a FJle obiect
can be safer 10 use.
In other words, 90% of what you might typically do with
Java I/O can use what we've already covered. • To read a text file, start with a FileReader
connection stream.
Q:What about the new I/O nlo classes added In 1.41
• Chain \he FileReader toa BufferedReader for
A.: The [ave.nlo classesbring a big performance efficiency.

improvement and take greater advantage of native • To parse a text file. you need 10 be sure the
capabilities of the machine your program Is runn ing
on. One of the key new features of nlo is that you have file is written with some way to recognize the
direct control of buffers. Another new feature Is non-
blocking I/O, which means your I/O code doesn't just sit different elements. Acommon approach is to
there, waItIng, if there's noth Ing to read or write. Some
of the existing classes (Including FllelnputStream and use some klnd ofcharacter to separate the
FlleOutputStream) take advantage of some of the new
features, under the covers.The nio classesare more individual pieces.
complicated to use, however, so unless you really need the • Use the String splitO method 10 split a String
new features, you might want to stick with the simpler
versions we've used here. Plus, If you're not careful , nio can upinto indiVidual tokens.AString with one
lead to a performance loss. Non-nlo I/O Is probably right separator will have two tokens, one on each
for 90% of what you'll normally do, especially if you're Just side of \he separator. The separator doesn~
getting started In Java. count asa token.

But you canease your way Into the nlo classes, by using
FilelnputStream and accessing its channelthrough the

getChannelO method (added to FllelnputStream as of
version 1.4).

you are here. 459

saving objects • vYou write a Dog class
10UOl \ ,,~S\()Y\·\1"'1
Versio" IP: AJig Serializatio" &otcha
1011 01 ".
Now you 've seen that I/O inJava is actually pretty simple, especially if 1010 1000010 ··
you stick to the most common connection/chain combinations. But ~~;~o10 1Q taSS
there's one issue you might really care about.
1~~0~10~1~0~1~~Ol ~;Ar;
Version Control is crucial!
Dog .class
!fyou serialize an object, you must have the class in order to
deserialize and use the object. OK, that's obvious. But what might • You serialize a Dog object
be less obvious is what happens if you changethe classin the using that class
meantime? Yikes. Imagine trying to bring back a Dog object when
one of its instance variables (non-transient) has changed from a • \DYou change the Dog class
double to a String. That violatesJava's type-safe sensibilities in a Big ~~~:~~i:~O~~~'\: .
Way. But that's not the only change that might hurt compatibility.
Think about the following: tlass >JeYSIO'l\

Changes to a class that can hurt deseriallzatlon: Ol 01 0 1. :H=12-~
Deleting an instance variable
Changing the declared type of an instance variable ;o~~~o:~:o
Changing a non-transient instance variable to transient
Moving a class up or down the inheritance hierarchy 1. 0 1. 10 10
Changing a class (anywhere in the object graph) from Serializable
to not Serializable (by removing 'implemen ts Serializable' from a Dog.c1ass
class declaration)
Changing an instance variable to static • You deserialize a Dog object
using the changed class
Changes to a class that are usually OK: 101101
Adding new instance variables to the class (existing objects will 10UOl ' "
deserialize with default values for the instance variables they didn't 101000010
have when they were serialized) 1010 10 0
Adding classes to the inheritance tree 01.010 1
Removing classes from the inheritance tree 10 0001 1010
Changing the access level of an instance variable has no affect on
the ability of deserialization to assign a value to the variable Co 00110101
Changing an instance variable from transient to non-transient 1. 0 1 10 1 0
(previously-serialized objects will simply have a default value for the
previously-transient variables) Dog.class

t\ass >Jeys',OYl 'IS
:H=12-~

• Serailization fails!!

The JVM says, "you can't
teach an old Dog new code".

460 cha pte r 14

Usi.,g the serialVersio.,UIP serialization an d file 110

Each time an object is serialized. the object (including When you think your class
every object in its graph) is 'stam ped' with a version might evolve after someone has
ID number for the object's class. The ill is called serialized objects from it•••
the serialVersionUlD, and it's computed based on
inform ation about the class structure . As an object is @ Use. the serialver command-line too'
being deserialized, if the class has changed since the
object was serialized, the class could have a different to get the version ID for your closs
serialVersionUID, and deserialization will faill But you
can control this. CD Paste the output into your closs

If you think there Is ANY possibility that public class Dog {
your class might evolve, put a serial version long .erialVersionOZD -
ID In your class. -6849194410154667110L;

When Java tries to deserialize an object, it compares private Strinq name;
the serialized object's serialVersionUID with that of the private int size ;
/ / method code here
class the JVM is using for deserializing the object For
~ Be sure that when you make changes to
example, ifa Dog instance was serialized with an ill of, the closs , you take responsibility in your
say 23 (in reality a serialVersionUID is much longer). code for the consequences of the changes
when theJVM deserializes the Dog object it will first you made to the clossl For example, be
compare the Dog object serialVersionUID with the sure that your new Dog closs can deal with
Dog class serialVersionUID. If the two numbers don't an old Dog being deserialized with default
match, rhejVM assumes the class is not compatible values for instance variables added to the
with the previously-serialized object, and you'll get an doss after the Dog was serialized.
exception during deserialization.
you are he re ~ 461
So, the solution is to put a serialVersionUID
in your class, and then as the class evolves, the

serialVersion UID will remain the same and the JVM

will say. "OK, cool, the class is compatible with this
serialized object." even though the class has actually
changed.

This works ()1lly if you're careful with your class
changes! In other words. YQU are taking responsibility
for any issues that come up when an older object is
brought back to life with a newer class .

To get a serialVersionUID for a class, use the serialver
tool that ships with your Java development kit.

Code Kitchen

'* *Code Kitchen

Let's mak the BeatBox save and

restore our lavorite pattern

462 chapter 14

serialization and file I/O

SavinG a 'eatJox pattern

Remember, in the BeatBox, a drum pattern is nothing more than a bunch of
checkboxes. When it's time to play the sequence, the code walks through the
checkboxes to figure out which drums sounds are playing at each of the 16
beats. So to save a pattern, all we need to do is save the state of the checkboxes.

We can make a simple boolean array, holding the state of each of the 256
checkboxes. An array object is serializable as long as the things in the array are
serializable, so we'll have no trouble saving an array of booleans.

To load a pattern back in , we read the single boolean array object (deserialize
it), and restore the checkboxes. Most of the code you've already seen, in the
Code Kitchen where we built the BeatBox GUI , so in this chapter, we look at
only the save and restore code.

This CodeKitchen gets us ready for the next chapter, where instead of writing
the pattern to a file, we send it over the networkto the server. And instead of
loading a pattern in from a file, we get patterns from the server, each time a
participant sends one to the server.

Serializing a pattern

This is an inner t\ass i'llSide
t.he Beat.Bo~ zede.

p u bli c cla ss MySendListene r implements Acti onL i{ste~nebr ~{ HIto. alnl haapnpednts.h.e.,hAend"l:i'hoenE~.'Ieernt.".\{.\.,r,e,ss t.he
p u blic void actionPerfo r med (ActionEvent a) .

Ztboolean [] =checkboxState new boolean [256]; t-- a rbooleatl array to hold t.he

for (int i = 0; i < 256; i++) { 01" eath the'kbo~.

JCheckBox check = (JCheckBox) checkboxList.get(i); g(WAeatrlrkta.hyteL.hsirsotta~. gtehott.thheetthkebtok~bso)~,Laitsldt
add it to t 0+ eath Otle, and
if (check.isSelected(» {

checkboxState[i] = true;

he boo/eatl array.

try {

FileOUtputStream fileStream = new FileOUtputStream(new File("Checkbox.ser"»;
=ObjectOUtputStream os new ObjectOUtputStream(fileStream) ;

os.writeObject(checkboxState);

catch(Exception ex) {

ex.printStackTrace();

} II close method
II close inner class

you are here). 463

deserlallzlng the pattern

Resfori.,g a Jea1tox patter"

This is pretty much the save in reverse... read the boolean array and use it
to restore the state of the GUI checkboxes, It all happens when the user hits
the "restore" 'button.

Restoring a pattern

public class MyReadInListener impleJDenta ActionLiataner

publiC void actionPerfor.med(ActionEvent a)

boolean [] checkboxState :;;;; null;

try (

FilelnputStream filaIn:;;;; new Filelnputstream(new File("Checkbox.aer"»;

ObjectInputstream is • new ObjectInputStream(fileIn) ; -the s"",~'e ~jed: i". the kil~~e

checkboxState = (boolean []) is. readObject () ; t--- Rao

catch (Exception ex) (ex. printstackTrac. () ; } boolea" array> o"d ta1-t It W . 0
boolea" arr0'i (Yl:1"etI'w. ytaoObjett
\'"d~."s a yet ~a-.te ok ~e Ob}et

for (int i :;;;; 0; i < 256; i++) ( aheokboxLillt. get (1) ;

JCb.eckBox check :::r (JCheckBox)

if (eheckboxState till (
ohaek.satsalected(trua) ;

} elae (
eheck.aetselected{false);

sequencer.stop();
buildTrackAndStart();

} I I close I118thod
II close inner class

rpen your penCiI------- - - - - - - - - - - ,

This version has a huge IImltatlonl When you hit the "serlatlzelt" button, It
serlaIIzes automatlca lIy,to a file named "Checkbox.ser" (which gets created If It
doesn't exist) . But each time you save,you overwrite the previously-saved flIe.
Improve the save and restore feature, by Incorporating a JFlleChooser so that
you can name and save as many different patterns as you like, and loadlrestore
from any of you r prevIously-saved pattern flies.

464 chapter 14

~yourpenCii serialization and file 110

can they he saved?

Which of these do you think are,or should be,
serlallzable? If not, why not? Not meaningful7
Security rlsk7 Only works for the CUTrent
execution of the JVM?Make your best guess,
without looking it up in the API.

Object type Serlallzable? If not, why not?
Object Ves I No
String Yes I No
File Yes I No
Date Ves I No
OutputStream Yes I No
JFrame Yes I No
Integer Yes I No
System Ves I No

Whars Legalil FileReader fileReadar ~ new FileReader() i
BufferedReader reader :: new BufferedReader (fileReader) ;
:lrclethe code fragments
FileC>utputStream f :: new FileOutputStream (new File ("roo . se.r") ) ;
nat would compile (assuming ObjectOutputstream 08 :: new ObjectOutputStream(f) ;

:hey're withIn a legaI dass). =BufferedReader reader:: new BufferedReader(new FileReade.r(file)) ;

KEEP String line null;
whila (line • reader.readLine()) != null) (
+-
malcecard(line) ;
RIGHT
ObjectInputStream is = new ObjectInputstream (new Fil&Outputstream("Game. ser")) ;

GameCharacter oneAgain = (Gamecharacter) is.readObject();

you are here ~ 465

exercise: True or False

This chapter explored the wonerful world of
Java 110. Your Job Is to decide whether each
of the followi ng lID-related state ments is
true or false.

1. Serialization is appropriate when saving data for non-java programs to use.
2. Object state can be saved only by using serialization.
3. ObjectOutputStream is a class used to save serialized objects.
4. Chain streams can be used on their own or with connection streams.
5. A single call to writeObjectO can cause many objects to be saved.
6. All classes are serializable by default.
7. The transient modifier allows you to make instance variables serializable.
8. If a superclass is not serializable then the subclass can't be serializable.
9. When objects are deserialized, they are read back in last-in, first out sequence.
10. When an object is deserialized, its constructor does not run.
11. Both serialization and saving to a text file can throw exceptions.
12. BufferedWriters can be chained to FileWriters.
13. File objects represent files, but not directories.
14. You can't force a buffer to send its data before it's full.
]5. Both file readers and file writers can be buffered.
16. The String splitO method includes separators as tokens in the result array.
17. Any change to a class breaks previously serialized objects of that class.

466 chapter 14

CoJe u serialization and file 110
lYlaonets
This one's tricky, ~ we promoted it from an Exerciseto full Puzzle status.

Reconstruct the code snippets to make a working Java program that

produces the output listed below? (You might not need all of the magnets,

and you may reuse a magnet more than once.)

-

seriali'Zable {
class DungeonGame implements

FileOutputstrearn fos = new short getZ () {
FileOutputst r e am( " dr~r, s e r " ) i return Zi

e.printStackTrace()i

009. close ( ) :

ObjectlnputStream ois = new int geU() {
ObjectlnputStream(fis);
return Xi

System.out.println(d.getX()+d.getY()+d.getZ())i

Filelnputstream fis = new ubl i c int x = 3;

FilelnputStream("dg.ser")j ransient long y = 4;

private short z = 5;

long getY() { class DungeOnTest <
return y;

ois ,close ( ) ; import java.io'~i

fos.writeObject(d);

~ - - - -• •"I } catch (Exception e) {

d = (DungeonGame) ois.readObject()j

ObjectOutputstream 009 = new oos .writeObject(d);

ObjectOutputStream(fos):

public static vo~'d main(String I J arg9) { 467
DungeonGame d = new DUngeonGame():

yo u are here ~

exercise sol utions

1. Serialization is appropriate when saving data for non:Java programs to use. False

2. Object state can be saved only by using serialization. False

3. ObjectOutputStream is a class used to save serialized objects. True

4. Chain streams can be usedon their own or with connection streams. False

5. A single call to writeObjectO can cause many objects to be saved. True

6. All classes are serializable by default. False

7. The transient modifier allows you to make instance variables serializable. False

8. If a superclass is not serializable then the subclass can't be serializable. False

9. When objects are deserialized they are read back in last-in, first out sequence. False

10. When an object is deserialized, its constructor does not run. True

11. Both serialization and saving to a text file can throw exceptions. True

12. BufferedWriters can be chained to FileWriters. True

13. File objects represent files, but not directories. False

14. You can't force a buffer to send its data before it 's full. False

15. Both file readers and file writers can optionally be buffered. True

16. The String splitf) method includes separators as tokens in the result array. False

17. Any change to a class breaks previously serialized objects of that class. False

468 chapter 14

serialization and file 110

Fit ~~ W1~ Help Es:apo class DungeonGame implements Serializable {

\ j ava DungeonTest public int x = 3;

12 transient long y = 4:
8
=private short z 5:

int getX() {
return Xj

}

long gety() {
return Yj

}

short getZ() {

return 2:

}
}

class DungeonTest {
public static void main(String [) args) (
DungeonGame d = new DungeonGame{)j
System.out.println(d'getX() + d.getY() + d.getZ{»j
try (
FileOutputStream fOB = new FileOutputStream{Udg.ser H ) :
ObjectOutputStream oos = new ObjectOutputStream(foB)j
oos.writeObject(d);
oos.close():

FilelnputStream fis = new FilelnputStream(Udg.ser n ) :

ObjectlnputStream ois = new ObjectlnputStrearn{fis):
d = (DungeonGame) ois.readObject();

ois.close();
catch (Exception e) {
e.printStackTrace()j

)

system.out.println(d.getX() + d.getY{) + d.getZ{»;

}

you are here. 469

15 networking and threads

Make a Connection

Connect with the outside world. Your Java program can reach out and touch a

program on another machine. It's easy. All the low-level networking details are taken care of by
classes In the java.net library. One of Java's big benefits is that sending and receiving data over
a network Is Just I/O with a slightly dIfferent connection stream at the end of the chain. If you've

got a BufferedReader. you can read.And the BufferedReader could care less if the data came

out of a file or flew down an ethernet cable. In this chapter we'll connect to the outside world

with sockets.We'll make cllentsockets.We'll make server sockets.We'll rnake clients and servers.

And we'll make them talk to each other. Before the chapter's done, you'll have a fully-functional,
multithreaded chat client. Old we just say multithreaded? Yes, now you will learn the secret of
how to talk to Bob while simultaneously listening to Suzy.

t his is a new chap ter 471

tbo)(. chat

You're working on a computer game .You and your team

.i~ B :O"~C:h:a:t -:r~~~;si~~"I~<.@t ~c::~~;1your chat message, and everybody in the Beat
are doing the sound design for each part of the game.

Using a 'chat' version of the Beat 'Box, your team can

collaborate-You can send a beat pattern along with __

getS So yO,u don't just get to rtad\ th e othder. .. ""'\<IO.sl'I"...• 0>"
e.... - ..pa",clpa. ",,,sages. yoU gel 10 oad an
<en ;;;;.<"" ...

,.
l

~~' ~,.f'· ,. ...... ,."mInestshaisgechinapthteer iwnec'orme gino.ginmge1.s0salgeeas'ranrweah.at ,t
pl<ry a bea lSpattern s,,,,ply by chclcing the , - ' me "'" ..... ee

Go .'-' _t \ t \ 1\ "", ,"-t''- , l' \\ to\!.

takes 10 ",ake a chat chenl hke th". We're r\~oc ,,.n " ,<t. """
even going 10 ,earn a hlde .boUI ",aking a Itf:.>.';,'f"I"n'". ..... <1' -;
"'"
cba IS,,"'" We'n save the fun Beat Be' Chat . ."

for the Code lGochen. but in mis chapter you \t0~0"""'"''"~''' "" ,.,fI'''''''
",iUwn"" Ludicrously Si",ple Chat Client and
Very Si",ple Chat Se",er that send and ,eceive <;t, s." """,

"''' m"",g'"

472 chapter '\5

networking and threads

Chat Program Overview

The Client has toknow

ahoutthe Server.

The Server has toknow
about ALL the Clienti.

How it Works: Client C

o Client connects to the server

Client A

G The server makes a Client A Server

connection and adds the client - ~V~, I'd lik~ to l.o9I~t
to the list of participants to tht t~ stHite

e Another client connects Client B Server

o Client A sends a message to -~~
the chat service I '.-~."Who took ~ lava liMf_ _---1 I~
---- .
o The server distributes the ~---. My OOhtl f
message to ALL participants Client A
(including the original sender) Server

Client A Server
Client B you are here ~ 473

socketconnecllons

The three things we have to learn to get the client working are :
1) How to establish the initial connection between the client and server
2) How to send messages UJ the server
S) How to receive messagesjrom the server
There's a lot of low-level stuff that has to happen for these things to work. But we're
lucky, because the Java API networking package (java.net) makes it a piece of cake
for programmers. You'll see a lot more GUI code than networking and I/O code.
And that's not all.
Lurking within the simple chat client is a problem we haven't faced so far in this
book: doing two things at the same time. Establishing a connection is a one-time
operation (that either works or fails). But after that, a chat participant wants to
send outgoing messages and simultaneously receive incoming 7TU'.SSages from the other
participants (via the server). Hmmmm... that one's going to take a little thought, but
we'll get there injust a few pages.

o Connect

Client connects to the server by

establishing a Socket connection.

Ma~ a sotlcd:. l.mIPlettiO'll to
J~I>.lbt.r.rO; .if. rort c;ooo

Client A

• Send

Client sends a message to the server

Client A

e Receive

Client gets a message from the server

Client A

474 chapter 15

networking and threads

Make a ttetwork Socket cotntectiott To make aSoc"ket

To connect to another machine, we need a Socket connection. connection, you need
A Socket (java.ner.Socket class) is an object that represents
a network connection between two machines. What's a to know ~ things
connection? A relationship between two machines. where two
pieces of software know about each other. Most importantly, about the server: %0
those two pieces of software know how to communicatewith it is, and which port
each other. In other words . how to send bits to each other.
its running OIL
We don't care about the low-level details, thankfully, because In other words,
they're handled at a much lower place in the 'networking
stack'. If you don't know what the 'networking stack' is, don't IP address and TCP
worry about it. It's just a way of looking at the layers that port l11U1lher.
information (bits) must travel through to get from aJava
7 Port 1l""'ba-
program running in aJVM on some OS, to physical hardware

(ethernet cables, for example). and back again on some other
machine. Somebody has to take care of all the dirty details.
But not you. That somebody is a combination of O~pecific
software and the Java networking API. The part that you have
to worry about is high-level-make that v~ high-level-and
shockingly simple. Ready?

= lr:ci ~orSocket chatSocket
new Socket(~196.164.1.103H, 5000);

r t1S the sa-vt:r

Client

ASocket connection means the two machines have
inforztlation about each other, including networl
location (IP address) and TCP port.

you are here ~ 475

well-known ports

Arep port Is Just attutltber. Well-known TCP port numbers
for common server applications
A16..bit ttutMber that identifies
aspecific prograttt Ott the server.

Your internet web (HTTP) server runs on port 80. That's a AseY"'er" l.4... helVe "p to b&5~b
standard. If you've got a Telnet server, its running on port
23. FTP? 20. POP3 mail server? 110. SMTP? 25. The Time diHf"r'etlt serve- apps 'nIIInil'\~
server sits at 37. Think of port numbers as unique identifiers. ~ per" pori:.
They represent a logical connection to a particular piece of
software running on the server. That's it. You can't spin your The TCPport
hardware box around and find a TCP port. For one thing,
you have 65536 of them on a server (0 - 65535). So they tuU1lbers frOttl 0 to 1023
obviously don't represent a place to plug in physical devices. are reserved for well-
They're just a number representing an application.
"known services. Don't
Without port numbers, the server would have no way of
use them for your own
knowing which application a client wanted to connect to. server programs!'"

And since each application might have its own unique The chat server we're
protocol, think of the trouble you 'd have without these
identifiers. What if your web browser, for example, landed writing uses port
at the POPS mail server instead of the HTTP server? The
mail server won 't know how to parse an HTTP request! And 5000. We just }tie"ked a
even if it did, the POPS server doesn't know anything about
servicing the HTTP request tuU1lber between 1024
and 65535.
When you write a server program. you'll include code that
tells the program which port number you want it to nul on 'Well, you might be able 10 use one of
(you'll see how to do this in Java a little later in this chapter). these.bul the sys-adrnln whereyou
In the Chat program we're writing in this chapter. we picked
50DD.Just because we wanted to. And because it met the work will probably kill you.
criteria that it be a number between 1024 and 65535. Why
I024? Because 0 through 1023 are reserved for the well-
known services like the ones we just talked about,

And if you 're writing services (server programs) to run on
a company network, you should check with the sys-admins
to find out which ports are already taken. Your sys-admins
might tell you, for example, that you can't use any port
number below, say, 3000 . In any case, if you value your limbs,
you won't assign port numbers with abandon. Unless it's
your home network. In which case youjust have to check with
your kids.

476 chapter 15

networking and threads

Q: How do you know the port IP address is like specifying a
particular shopping moll, soy,
number of the server program you "Flatirons Marketplace"
want to talk to 7
or number is like naming
A.: That depends on whether the a specific store, soy,
"Bob's CD Shop"
program is one of the well-known
services. If you're trying to connect OK,you got a Socket connection .The client and the
to a well-known service, like the ones server know the IP address and Tep port number for
on the opposIte page (HTIp' SMTP, each other. Now what1 How do you communicate
FTP,etc.) you can look these up on over that connection 11n other words, how do you
the Internet (Google "Well-Known move bits from one to the other? Imagine the kinds of
TCP Port"). Or ask your friendly messages your chat client needs to send and receive.

eighborhood sys-adrnin. Client Server

But if the program isn't one of the you ar e here ~ 477
well-known services,you need to
find out from whoever Is deploying
the service. Ask him. Or her.Typically,
if someone writes a network service
and wants others to write clients for
it , they'll publish the lP address, port
number, and protocol for the service.
~or exampie, if you want to write a
client for a GO game server, you can
visit one of the GO server sites and
find Information about how to write a
client for that particular server.

Q: Can there ever be more than

one program running on a single
port7 In other words, can two
applications on the same server have
the same port number7

A.: Nol If you try to bl nd a prog ram

:0 a port that Is already in use,you'll
get a BindException. To bind a program
:0 a port just means starting up a

server application and telling It to run
a particular port. Again, you 'll learn

~ore about this when we get to the
server part of this chapter.

reading from a socket

To read data frotH aSocket use a / Tht.~M\tI.t1f~\oOrUl:.-.I,"~""T,,""O,Lh"tgL:~rb~~-.(I'\f-K.oii,unoU+''rf.ohtUa.htka"nt0o-~.0lt0:ris.
SufferedReader

To communicate over a Socket connection, you use streams.
Regular old I/O streams.just like we used in the last chapter. One
of the coolest features in java is that most of your I/O work won't
care what your high-level chain stream is actually connected to. In
other words, you can use a BufferedReader just like you did when
you were writing to a file, the difference is that the underlying
connection stream is connected to a Socket rather than a File!

o Make a Socket connection to the server

Socket chatSocket ~ new Socket("127.0.0.1", 5000);

z:"-.. /27.0.o'N.J~dsi$J t.+hf.~ I~:d~~~ tor '11~lhoti.. .
e rt. tub t Youyou.rS~V"tt~- 01U\ dlis.s'ojII\hSbI~I Yot. )r~ I.lI t.od~ i.s... . ) 'n
I~
"")\t1J1\9 01\.

)\d-aIOtlt "'clth. 'bI dnd

Make an InputStreamReader chained to the Socket's rr>e.

low-level (connection) input stream

e Make a BufferedReader and readI 1L. &oH~(dReAdt:r b:> ~~ d 1 - tnt 10-.1-
C\\("h'<IoaItiv!"ttSoVb''lC-\,'t,(at"u1"O: Rle\ daS~"_t.(Twtan'"it\--..I wAasJ.t\~-'.ra(i)"7ft\ tr.( ~'UJ,.. .\• ..l.)

( t 'J"'''

BufferedReader reader = new BufferedReader (stream) i
String message = reader.readLine();

buffered characters converted to characters bytes from server - ---- - -
I I 1'+·--- :'~cbhuafrfaecretedrs chained to characte.rs ,.chained to 011010011 _
I

BufferedReader InputStre.amRe.ader Socket's input stream r. I

Client (we. don't need to know Server

the. aCf\JQ1 class)

478 chapter 15

networking and threads

fo write data to aSocket use a
Prh1tWriter

We didn't use PrintWriter in the last chapter, we used BufferedWriter. We have
a choice here, but when you 're writing one String at a time, PrintWriter is the
standard choice. And you'll recognize the two key methods in PrintWriter,
printO and println () IJust like good 01' System.out,

o Make a Socket connection to the server

Socket chatSoeket = new Soeket("127.0 .0.1",

e Make a PrintWrlter chained to the Socket's low-level
(connection) output stream

=PrintWriter writer new PrintWrit8r(chatsocket .qetoutputStream(»;

I

e ~ (print) something . l ~t ClIO ~ ..,\\at it. se..o.s·
writer.println("messaqe to send"); ~rrl."1UI "0 aods a I\tfoI \ ,roe aT. .
owriter.print("another -tht "CW \I"t.·
message"); ~rri"t() cl.~"' L" J

iu

characters bytes to server

I . I----+~ message..." ~ 011010011
chained to ' - - - - _ - - I

PrintWriter Socket's output

stream (we don't need

to know the actual class)

you are here) 479

writing a client

fhe PailyAdvieeCliet1t

Before we start building the Chat app,
let's start with something a little smaller.
The Advice Guy is a server program that
offers up practical, inspirational tips
to get you through those long days of
coding.
We're building a client for The Advice
Guy program, which pulls a message
from the server each time it connects.
What are you wailing for? Who kncws
what opportunities you've missed
without this app.

o Connect The Advice Guy

Client connects to the server and gets an
input stream from it

Client

eRead

Client reads a messQge from the server

Client A

480 chapter 15

networking and threads

PailyAdviceCliet1t code

This program makes a Socket, makes a BufferedReader (with the
help of other streams), and reads a single line from the server
application (whatever is running at port 4242).

r_.,.-Limport is in ,o"a.nt1:.
java .io.*; L-_~ tlass ;:,Q<o~~
.,}

import java .net.* ;~

public class DailyAdviceClient

=InputStreamReader streamReader new InputstreamReader(s.getlnputstream(»;

BufferedReader reader = new BufferedReader (streamReader); thain a B~~e\'"edReode\'" to
f---"" art Irty~+.streaMRe ade\'" to

the inf~t str'ea", t\'"OM the
Sotkd:..

~ o .string advice = reader .readLine();

System.out.println("Today you should:
" + advice) ; t his readL ' 0IS'" EwXeArec~TihL~' (

Bt he sa"'e asIh;e~ 't a

",UeredR. d
lol tahBerf.Arwot-etedaresd,eWrby"l'httahiehe1d;''''t'eoyaOl.Ft ILE..
reader. close () ; ~this doses AI-I- the streaMS r-Ih

la

0:writer dOt;sh'tklah orw. er "'ethod, the
lare where
catch(IOException ex) { the lharal ters
"'e -tro",.

ex .printStackTrace();

public static void main (String[] args)

=DailyAdviceClient client new DailyAdviceClient();

client. go () ;

you are here . 481

socketconnecUons

Test your memory of the streams/classes for reading and writing from a
Socket.Try not to look at the opposite pagel

To read text from a Socket:

, .. - - .

Client 'M'iU!dra.., il'l t.h~ thaill o-f sttea....s t.he tlitl'lt. !
I.I$tS to read .f"'OM t.ht st'r'/er
\

\'

server

To send text to a Socket 'M"iWdraw ill the thaill o-f sttUMS the t1iblt
Client lAStS to smd ~i"5 to the ~ver

rpen your pencU - - - - - - - - - - - - - - - - - - .

Fill In the blanks:

What two pieces of Information does the client need in order to make a
Socket connection with a server?

Which TCP port numbers are reserved for'well-known services'like HTTPand FTP7

TRUE or FALSE: The range of valid TCP port numbers can be represented
by a short primitive?

482 chapter 15

Wrifittg a sitttple server networking and threads

So what's it take to write a server application? Just a ~ ~~ ~
couple of Sockets. Yes, a couple as in two. A ServerSocket,
which waits for client requests (when a client makes a . ) ...
new Sockett) and a plain old Socket socket to use for
communication with the client. \

How it Works:

o Server application makes a ServerSocket, on a specific port

SarverSocket serverSock: new S&rV8rSocket(4242);

This starts the server application listening
for client requests coming in for port 4242.

e Client makes a Socket connection to the server application .,SD",,~~et.
Socket sock = new Socket ("190 . 165. 1 . 103" , 42(2);
~ 'II'':~ ;';;; ~ '
Clie.nt knows the IP address and port number rs::~~
(published or given to him by whomever ..... ..~ .~ ....
configures the server app to be on that port)
l

e Server makes a new Socket to communicate with this client

Socket sock = serverSock.accept();

The acceptO method blocks (just sits there) while
it's waiting for a c1ie.nt Socket connection. When a
client finally tries to connect, the method returns
a plain old Socket (on a different port) that knows
how to communicate with the dient (i.e.. knows the
client's IP address and port number). The Socket is on
Cl different port than the ServerSocket, so that the
ServerSocket can go back to waiting for other clients.

you ar e here. 483


Click to View FlipBook Version