Vous êtes sur la page 1sur 38

Basic Programming using Java

ut = new Da Object Serialization

Streams and Object Serialization


At the end of this chapter you will be able to understand the streams and use them for input-output operations.

SCOPE
9.1 Introduction to Streams 9.2 InputStream Class 9.3 OutputStream class 9.4 ByteArrayInputStream Class 9.5 ByteArrayOutputStream Class 9.6 Files Streams 9.6.1 FileInputStream Class 9.6.2 FileOutputStream Class 9.6.3 File Class 9.7 Filtered Streams 9.7.1 Buffered Streams 9.7.1.1 BufferedInputStream Class 9.7.1.2 BufferedOutputStream Class 9.7.2 DataInputStream Class 9.7.3 DataOutputStream Class 9.7.4 PrintStream Class 9.8 Character Array Streams 9.9 Buffered reader and writer classes 9.10 9.11 9.12 RandomAccessFile class Object Streams Case StudyCollege Student Enrolment System (Contd.)

Copyright 2006, Tata Consultancy Services Limited (TCS).

275

Basic Programming using Java

Streams and Object Serialization

9.1 Introduction to Streams


Most of the programs cannot accomplish their goal without writing data or reading data from some external source. The java.io package caters to such requirements of input output. In Java the input output is based upon the concept of streams, which is the sequence of bytes travelling over a communication path. The communication path may be a memory-to-memory transfer of bytes, may span a file system or even networks. Java provides two major classes for input output of byte streams - the InputStream class and the OutputStream Class. Apart from these there are the Reader and Writer classes, which allow you to handle a 16-bit value contrary to the byte streams. Other types of classes like the RandomAccessFile class, the ObjectStream classes are some special classes that provide various other useful features for I/O.

9.2 InputStream Class


The InputStream class represents the basic input stream. It provides the basic functionality for all the other classes extending from it, like the FileInputStream, ByteArrayInputStream etc. The InputStream class provide some general functions, for example the read(), skip() functions etc., which these sub classes can use. Some of these functions are given below: The read() method is used to read data from the streams. It is the most basic and frequently used method. It takes the following forms:
public abstract int read() throws IOException public int read(byte b[ ]) throws IOException public int read(byte b[ ], int offset, int length) throws IOException

The read() method reads data in the form of bytes from the stream. This method performs a blocking call, i.e., if there are some bytes available in the stream it picks them up a single byte at a time and returns it, otherwise it waits. For example, if you are trying to read a stream from the network, the read method would keep on waiting for the bytes even if they have not yet arrived. As said earlier the read() method reads one byte at a time and returns it, on encountering the end of stream it returns -1. This method throws an IOException, so while using it you must enclose it within try and catch block. The read() method with byte array as a parameter reads the data from the input stream and fills it in the byte array. After performing the read you can process the bytes stored in the array at one time. This method may fill the array with lesser bytes than it can actually hold. This situation arises when the stream is going to reach the end and there are fewer characters left in it as compared to the size of the byte array.
Copyright 2006, Tata Consultancy Services Limited (TCS).
276

Basic Programming using Java

Streams and Object Serialization

The read(byte b[ ], int offset, int length) method of this form reads the bytes from the input stream and stores it in the byte array starting at the specified offset up to the length of the bytes read from the stream. Consider the following example, which reads the bytes from the input stream and displays them. When you execute the program, the read() method waits for some input. As you type some characters, it does not immediately displays the characters, but waits for you to press enter. After that it reads all the characters one by one and returns them. Then they are displayed, and while displaying them they are type cast to character as the read() returns the integer value of the bytes read. In order to terminate the read, you have to provide the end of file character which can be keyed in as cntl + z in DOS environment. Note that the java.io package is imported because we are dealing with the input/output functions.
import java.io.*; class Read_Byte { public static void main(String args[]) { int b=0; while( b != -1) { try { b=System.in.read(); System.out.println((char)b); }catch(IOException e) { System.out.println("Error in reading "); } } } }
Listing 9.1 Using the read() function

The next method in the InputStream class is the skip() method. It takes the form as:
public long skip(long n)

The skip() method skips from the current position the number of bytes passed as a parameter. It internally uses the read() method in order to skip the bytes, so this method also acts as a blocking call. It returns the number of bytes read or -1 if it encounters the end of file.
Copyright 2006, Tata Consultancy Services Limited (TCS).
277

Basic Programming using Java

Streams and Object Serialization

Since read blocks and waits at the stream for the incoming bytes, it is always better to check whether there are bytes available in the stream or not. For this you use the available() method. The available() method returns the number of bytes you can safely read. So before using the read() you can use the available() method to ensure that there are some bytes in the stream.
public int available() throws IOException

Once you are done with a stream, you must close it using the close() method, however it is not necessary as it automatically gets closed during the garbage collection. Most of the operating systems impose a limit on the number of opened files, and though the streams may automatically get closed during garbage collection, freeing up of the resources becomes important. The close method takes the form:
public void close() throws IOException;

9.3 OutputStream class


The OutputStream class is complementary to the InputStream class. It also acts a base class for all the other classes for output that extends from it. It defines some general functions for the other output stream classes. The most important function in this class is the write() function. Similar to the read() method it takes three forms:
public abstract void write(int a) throws IOException public void write (byte b[ ]) throws IOException public void write throws IOException (byte b[ ], int offset, int length)

The write() method writes the data to the output stream. The write(int) writes the parameter passed as integer to the output stream. The write(byte b[ ]) writes the contents of the byte array passed as a parameter to the output stream. The write (byte b[ ], int offset, int length) writes to the output stream the number of bytes from the byte array determined by the length parameter, starting at the specified offset. Consider the following example, which reads the bytes from the input stream and writes them back to the output stream:

Copyright 2006, Tata Consultancy Services Limited (TCS).

278

Basic Programming using Java

Streams and Object Serialization

import java.io.*; class Write_Byte { public static void main(String args[]) { int b=0; while( b != -1) { try { b=System.in.read(); System.out.write((char)b); }catch(IOException e) { System.out.println("Error in reading "); } } } }
Listing 9.2 Demonstrating the write() function

Apart from the write() method, there is a method for flushing the output stream. Flushing the stream means pushing the leftover data in the stream to the destination. You can ensure that the data in the stream has reached the destination by using the flush() method.
public void flush() throws IOException

Similar to the input stream, the output stream must be closed after you have finished using it. This can be done with the close() method.
public void close() throws IOException

9.4 ByteArrayInputStream Class


The ByteArrayInputStream is an implementation of the input stream class. It is used to perform input output using a byte array. The constructors, which are used to create the ByteArrayInputStream, are as follows:
public ByteArrayInputStream(byte[ ] byteArray) public ByteArrayInputStream(byte[ ] byteArray, int offset, int length)

Copyright 2006, Tata Consultancy Services Limited (TCS).

279

Basic Programming using Java

Streams and Object Serialization

They use an array of bytes as the source from which you would be taking the input. You also can select a range as the source from a given byte array by providing the offset or position in the array from where you want to read and the number of bytes to be read from there on.

9.5 ByteArrayOutputStream Class


The ByteArrayOutputStream class is an implementation of the OutputStream class. It facilitates storing the output in a buffer that is read from a stream. You can then manipulate this buffer and use the output as desired by the program. It has two constructors:
public ByteArrayOutputStream() public ByteArrayOutputStream(int initialsize)

The initialsize parameter specifies the size of the buffer to be created to store the bytes. The data present in the byte array output stream is extracted using the toByteArray() method. This function returns the bytes present in the buffer in the form of an array.
public synchronized byte[ ] toByteArray()

Consider the following example, which creates a bytearray output stream and writes a string to it. Then a ByteArrayInputStream object is created to trap the data present in it using the method toByteArray() in the constructor. This stream is checked for the availability of data using the available() method. A byte array is then created with the same size as that of the bytes present in the stream, which is used to read the data from the byte array input stream.
import java.io.*; class ByteArrayIO { public static void main(String args[]) throws IOException { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); String str = "Sending the output to the stream";

for (int i=0; i < str.length(); i++) { outStream.write(str.charAt(i)); // reading the string character by // character }

Copyright 2006, Tata Consultancy Services Limited (TCS).

280

Basic Programming using Java

Streams and Object Serialization

ByteArrayInputStream inStream = new ByteArrayInputStream ( outStream.toByteArray()); int numBytes = inStream.available(); byte buff[] = new byte[ numBytes]; int numBytes); System.out.println("The streamcontains : " + new String(buff)); } }
Listing 9.3 I/O using byte array streams

bytesRead

inStream.read(buff,

9.6 File Streams


The stream-based input output to and from the files is basically performed through the classes like the FileInputStream and FileOutputStream classes. There is also a class called the File class, which allows you to access the files or the directories. The direct or the random access input output to the file could be done through the RandomAccessFile class. A description of these classes is given below:

9.6.1 FileInputStream Class


The FileInputStream class allows obtaining a stream directly from a file. It is a subclass of the InputStream class. The objects of the FileInputStream class can be created using the following constructors, which either take the filename or the object of the File class as a parameter. The File class would be dealt with later in this session.
public FileInputStream(String name) public FileInputStream(File obj)

The listing 9.4 creates a file object with a String object as a parameter. It reads the contents from the file given as the source, and they are printed thereafter.

Copyright 2006, Tata Consultancy Services Limited (TCS).

281

Basic Programming using Java

Streams and Object Serialization

import java.io.*; class FileInp { public static void main(String args[]) throws IOException { FileInputStream fin = new FileInputStream ("write_byte.java"); int i=0; while ( i != -1) { i=fin.read(); System.out.println((char)i); }

} }
Listing 9.4 Reading from a file

9.6.2 FileOutputStream Class


The FileOutputStream class is the subclass of the OutputStream class and it is used to attach the output stream to a file. It is created using the following constructors:
public FileOutputStream(String name) public FileOutputStream(File obj)

They take the filename as an argument that can be specified as a String or a File object. While reading a file, if an attempt is made to read beyond the end of file, an IOException is thrown. Consider the following example, which opens a file for output and writes some contents in it. The file is then closed and the contents of the same file are read. This example shows you the usage of the FileInputStream and FileOutputStream classes.

Copyright 2006, Tata Consultancy Services Limited (TCS).

282

Basic Programming using Java

Streams and Object Serialization

import java.io.*; class FileIO { public static void main(String args[]) throws IOException, FileNotFoundException { FileOutputStream fout = new FileOutputStream("temp"); String text = "This file is created temporarily for input output"; for(int i = 0; i< text.length(); i++) { fout.write(text.charAt(i)); } fout.close(); FileInputStream fin = new FileInputStream("temp"); int c=0; while( c != -1) { c=fin.read(); System.out.print((char) c); } } }
Listing 9.5 Program showing file input and output

9.6.3 File Class


The File class is used to obtain information about a file. For this you need to create the object of the File class specifying the name of the file that you want to use or for which you want to obtain some information. The constructors provided in the File class are as follows:
public File(String path) public File(String path, String name) public File(File dir, String name)

Copyright 2006, Tata Consultancy Services Limited (TCS).

283

Basic Programming using Java

Streams and Object Serialization

The first constructor creates a File object with a String as parameter that determines the complete path of the file, for example c:\Java\sourcefiles\FileIO.java. The next constructor divides the path between the directory path and the filename. The third constructor can take the File object itself specifying the directory path and the filename given additionally as String. This is very useful when you want to process different files present under the same directory. You can create the File object of that particular directory and reuse it for creating the File object for the files present under it. The File class provides a set of methods, which gives a lot of information about a file. Some of these methods are given below:
public String getName() public String getPath() public String getParent() public boolean exists() public boolean canWrite() public boolean canRead()

The getName() method returns the name of the file( the file may be an ordinary file or a directory file), the getPath() get the path of the file starting from the root directory, the getParent() method returns the parent directory of a file, the exists() method checks for the existence of a file, the canWrite() method tells whether the file has the write permission and the canRead() method tells whether the file has the read permission or not. There are many more functions apart from these functions. Take a look at the following example, which demonstrates how to use the File class. It creates the File object for a specific directory and lists down all the files under it with some of their attributes.
import java.io.*; class FileApp { public static void main(String Args[]) { File Dir = new File("\\prog8"); String fileNames[] = Dir.list(); for(int i=0; i < fileNames.length; i++) { System.out.println("FileName : " + fileNames[i]); File f = new File(Dir + "\\" + fileNames[i]);
Copyright 2006, Tata Consultancy Services Limited (TCS).
284

Basic Programming using Java

Streams and Object Serialization

System.out.println("Read permission : " + f.canRead()); System.out.println("Write permission : " + f.canWrite()); System.out.println("File size(in bytes) : " + f.length()); } } }
Listing 9.6 Demonstrating the usage of File object

9.7 Filtered I/O


The filtered input output stream classes provide the basic capability to create one stream from another. Using this concept we can create a stream and pass on the same stream reference to create another stream. This is one of the very powerful aspects of the streams because by using the filtered streams you can chain one stream to another. The chaining of the streams helps the resulting stream to adapt to the program needs in a better way. For example, the OutputStream class provides the write() method, which is a very basic method, used only to write the bytes to the output stream. When we chain this stream to DataOutputStream( a specialist class for outputting data) , all of a sudden we discover that we have a numerous other forms of write() method available to us, for example for writing integers, float etc. For the filtered I/O there are two main classes called the FilterInputStream and the FilterOutputStream class. They are abstract classes and they act as base classes for all other classes performing filtered I/O. These classes internally make use of the variables System.in and the System.out. So while chaining one stream to another, we may be able do the nesting or sequencing of the streams to whatever level, they all are accessing the basic input or output streams using the System.in and the System.out variables.

9.7.1 Buffered Streams


We have seen that by using the basic input output streams we are able to read or write one byte at a time. This may not be always desirable to us, for example, when we are writing to the disk using the write() method that writes one byte at a time. For every write operation you will be going to the OS again and again requesting to write the data, this will cut down on performance drastically. Instead of this, there should be a mechanism by which you should be able to buffer or cache your data beforehand and perform the I/O through it less frequently. Buffered streams are used to temporarily cache the data that is read from or written to the streams. For example, when the buffered input is performed a large amount of input can be taken collectively in a buffer before it reaches the program. The program can then apply numerous reads to pick up the data from the buffer and use it. Similarly, while
Copyright 2006, Tata Consultancy Services Limited (TCS).
285

Basic Programming using Java

Streams and Object Serialization

performing the output buffering, the program can write the data to the intermediate buffer and when the buffer gets full automatically the data is delivered to the destination or by calling the flush() method the data is pushed to the destination stream.

9.7.1.1 BufferedInputStream Class


The BufferedInputStream class is a filtered stream class that facilitates you to perform the input buffering. It automatically creates a buffer temporarily for the input stream and reads the data in it from the input stream. It is created using the following constructors:
public BufferedInputStream(InputStream in) public BufferedInputStream(InputStream in, int Buffersize)

The first constructor takes the object of the InputStream class since the BufferedInputStream class is a filter. It creates a 32-byte buffer automatically. With the help of the second constructor you are also able to specify the size of the buffer that temporarily gets created. BufferedInputStream class overrides the methods of the InputStream class and does not introduce any new methods of its own. The listing 9.7 shows how to accept the buffered input:
import java.io.*; class FileInp { public static void main(String args[]) throws IOException { FileInputStream fin = new FileInputStream ("write_byte.java"); BufferedInputStream bin = new BufferedInputStream (fin); int i=0; while ( i != -1) { i=bin.read(); System.out.println((char)i); }

} }
Listing 9.7 Using BufferedInputStream

The output would be the same as that of Write_Byte.java class


Copyright 2006, Tata Consultancy Services Limited (TCS).
286

Basic Programming using Java

Streams and Object Serialization

9.7.1.2 BufferedOutputStream Class


The BufferedOutputStream class allows you to do the output buffering. The BufferedOutputStream class overrides the methods of the OutputStream class and does not introduce any new methods of its own. It is created using the following constructors:
public BufferedOutputStream(OutputStream out) public BufferedOutputStream(OutputStream Buffersize) out, int

The first constructor is having only the OutputStream as a parameter and in the next constructor you are also able to determine the buffer size for the output.

9.7.2 DataInputStream Class


The DataInputStream class is also a stream filter, which takes the reference of the InputStream class. It can be created using the following constructor:
public DataInputStream (InputStream in)

The DataInputStream class provides additional methods to allow primitive data types and some other types to be read than just the bytes. This class implements the DataInputInterface, which lists down a whole range of methods for taking input. Some of these methods are given below:
public boolean EOFException readBoolean() throws IOException,

public byte readByte() throws IOException EOFException public char readChar() throws IOException, EOFException public short readShort() throws IOException, EOFException public int readInt() throws IOException, EOFException public long readLong() throws IOException, EOFException public float readFloat() throws IOException, EOFException public double readDouble() throws IOException, EOFException

9.7.3 DataOutputStream Class


The DataOutputStream Class is complementary to the DataInputStream Class. It has the following constructor:
287

Copyright 2006, Tata Consultancy Services Limited (TCS).

Basic Programming using Java

Streams and Object Serialization

public DataOutputStream(OutputStream out)

This class implements the DataOutput interface, which has various method prototypes for describing the output in the form of primitive or other data types. Some of these methods are given below:
public void writeBoolean(boolean b) throws IOException public void writeByte(int b) throws IOException public void writeChar(int c) throws IOException public void writeShort(int c) throws IOException public void writeInt(int i) throws IOException public void writeLong(long l) throws IOException public void writeFloat(float f) throws IOException public void writeDouble(double d) throws IOException

Consider the listing given below which reads the input in the form of primitive data types and stores them in respective variables. Then it uses those variables to write to the output stream. You must realize that the methods in the DataInput and DataOutput interface are complementary, i.e., if you are writing an integer to a stream using the writeInt() method you need to read it using the readInt() method.

Copyright 2006, Tata Consultancy Services Limited (TCS).

288

Basic Programming using Java

Streams and Object Serialization

import java.io.*; class DataInputOutput { public static void main(String args[ ]) throws IOException { char c1=' '; int i1=0; double d1=0.00; DataInputStream din = new DataInputStream(System.in); DataOutputStream dout = new DataOutputStream (System.out); System.out.println("Enter a character, Integer and a double value : \n"); c1=din.readChar(); i1=din.readInt(); d1=din.readDouble(); dout.writeChar(c1); dout.writeInt(i1); dout.writeDouble(d1); } }
Listing 9.8 Using DataInputStream and DataOutput Stream classes

9.7.4 PrintStream Class


The PrintStream class provides the methods to print all types of data including the object types to the stream. It is a filter class, and it takes the output stream as an argument. It has two constructors, where one simply creates the stream, attaching it to the output stream, and the other constructor creates a stream, which caters to the automatic flushing of the streams as soon as a \n is encountered .
public PrintStream( OutputStream out) public PrintStream( OutputStream out, boolean autoflush)

It has the methods print() and println() which are extensively overloaded for the printing of the data ranging from the primitive data elements to the object types. The System.out object, which you have been using through out your programs, is also an instance of the PrintStream class. To enable the PrintStream print the string representation of any type of object passed as an argument in the print() or println() method, that objects class must override the toString() method determining the String representation of the class(Refer to the listing 5.12 creating your own exception)

Copyright 2006, Tata Consultancy Services Limited (TCS).

289

Basic Programming using Java

Streams and Object Serialization

9.8 Character Array Streams


Till now we have been dealing with the kinds of streams that perform byte I/O. The benefit of the character streams is that it treats the stream as a stream of characters than a stream of bytes. So instead of reading byte by byte as in case of the byte streams it performs I/O with 16 bits values at a time. There are two types of the character array stream classes, the CharacterArrayReader() and the CharacterArrayWriter() classes. These classes contain the following constructors:
public CharacterArrayReader(char buf[ ]) public CharacterArrayReader(char buf[ ], int offset, int length) public CharacterArrayWriter() public CharacterArrayWriter( int size)

Consider the following example in which CharacterArrayWriter() class is created and some characters are fed into it. Then a CharacterArrayReader() class is created which reads out its contents, for this it has to use the toCharArray() function which returns everything present in the stream in the form of a character array. The character array can now be used in the application. In this listing, the StringBuffer class is used for the array manipulation. The StringBuffer class is more or less like the String class, but has a collection of different functions for string handling. The StringBuffer class allows you to create the strings, which can grow in size, insertions of substrings are possible inside them etc. Internally, the String class also uses the StringBuffer for many important functions or features, like overloading the (+) operator. In the listing 9.9, the method append() is used to add character one by one to the StringBuffer object. Thereafter, it is displayed.
import java.io.*; class CharRead { public static void main(String args[]) throws IOException { CharArrayWriter charOut = new CharArrayWriter(); String str character input output"; = "Demonstrating character by

for (int i=0; i< str.length(); i++) { charOut.write(str.charAt(i)); } CharArrayReader charIn = new CharArrayReader(charOut.toCharArray());

Copyright 2006, Tata Consultancy Services Limited (TCS).

290

Basic Programming using Java

Streams and Object Serialization

StringBuffer strbuf = new StringBuffer(""); int c = 0; while( (c = charIn.read()) != -1) { strbuf.append((char)c); } System.out.println("The characters read are : " + strbuf.toString()); } }
Listing 9.9 CharacterArray input output

9.9 Buffered Reader and Writer Classes


The BufferedReader and BufferedWriter classes perform the input output in the form of characters. These classes are analogous to the BufferedInputStream and BufferedOutputStream classes as they too buffer the data for input output operations. The BufferedInputStream class provides a very important method called the readLine() method that is used to read Strings from the streams. In Java 1.1 this method was a part of the DataInputStream class. In order to use the BufferedReader class, you have to create the object of the InputStreamReader class which takes the object of the InputStream class. This stream can now be sent as an argument to the BufferedReader class. The following example demonstrates the use of the BufferedReader class and the readLine() method in it.
import java.io.*; class read_Line { public static void main(String args[]) throws IOException { InputStreamReader in = new InputStreamReader(System.in); BufferedReader inBuf = new BufferedReader(in); String line; line = inBuf.readLine(); System.out.println(line); }

}
Listing 9.10 Buffered reader and writer classes

It would show the complete string, that you gave as an input.


Copyright 2006, Tata Consultancy Services Limited (TCS).
291

Basic Programming using Java

Streams and Object Serialization

9.10 RandomAccessFile Class


Using the random access file we can write or read data at any specific location in the file. The random access file can be created using the RandomAccessFile class. Using this class we can write or read at any location in the file rather than writing or reading as a continuous stream of data. The RandomAccessFile class provides two constructors in order to create the random access files. These constructors takes two parameters, the filename as String or a File object, and the mode in which you want to open the file. These modes are r for the read only mode and rw for the read-write mode. They are given below:
public RandomAccessFile(String filename, String mode) public RandomAccessFile(File filename, String mode)

The RandomAccessFile implements both the DataInput and DataOutput interfaces. Because of this, all the methods for reading and writing the primitive data types and other types are available to you. Apart from this, it gives you the methods seek(), getFilePointer() and length() which are very useful for random file I/O. The seek() method takes you to a particular location in the file. The getFilePointer() returns the current location in the file and the length() function gets the length of the file in bytes. Consider the following example which demonstrates how to create and use the random access file:
import java.io.*; class Random_FileIO { public static void main(String args[ IOException { RandomAccessFile empfile RandomAccessFile("emp.txt", "rw"); int eid = 24; boolean status = true; float sal = 15000; empfile.writeInt(eid); empfile.writeBoolean(status); empfile.writeFloat(sal); empfile.seek(0); System.out.println("Employee empfile.readInt()); id : " +

])

throws

new

Copyright 2006, Tata Consultancy Services Limited (TCS).

292

Basic Programming using Java

Streams and Object Serialization

System.out.println("Status(Active/inactive) : " + empfile.readBoolean()); System.out.println("Salary : " + empfile.readFloat());

} }
Listing 9.11 Create and use random access file

9.11 Object Streams


As you have seen in the previous listing, when you are reading or writing data to a file, you are using the variables one by one in the output statement. Consider a case where you have made a class say Employee which is used to stores the information about the employees. You instantiate this class and read the details of an employee in this object. Now you want to store the details contained in this object permanently in a file. What you possibly would start doing is break the class apart and start writing the data members element by element. It is absolutely undesirable as it fails the purpose of creating the object. If you want to store an object in a file, there should be a way that the whole object be written as a single entity than by breaking it in its individual elements and sending them one by one to a file. Through object serialization it is possible to send an object to be written to a file as a wholesome single unit. The saving of an object with its current state and retrieving it as the same original object later on is called persistence. This essentially means that you saved an object in a file, closed the program and at a later point of time you reopened the file and were able to obtain the object in the same state as they were written. The classes which are used to perform object serialization are the ObjectInputStream and the ObjectOutputStream classes. These classes implement the ObjectInput and ObjectOutput interfaces respectively. The ObjectInput interface provides the readObject() method to read objects from the stream and the ObjectOutput interface has the writeObject() method to write objects to the stream. These methods are capable of writing the objects of only those classes which implements the Serializable interface. They take the form as:
public abstract Object ClassNotFoundException, IOExcepion public abstract IOExcepion void readObject() throws

writeObject(Object

obj)

throws

Consider the following example, which serializes the class called SerialApp which has one dummy data member int i. Note that the class SerialApp is implementing the interface Serializable. An object of the ObjectOutputStream is made which takes in the
Copyright 2006, Tata Consultancy Services Limited (TCS).
293

Basic Programming using Java

Streams and Object Serialization

object of FileOutputStream that is attached to a file. Then an object of the class SerialApp is made and some arbitrary values are put in the variable i and these objects are written using the writeObject() method. The stream is then closed and an object of the ObjectInputStream is made which takes the object of the FileInputStream attached to the same file as an argument. The readObject() method is then used to read the objects from this file.
import java.io.*; public class SerialApp implements java.io.Serializable{ public int i ; public static void main (String args[ ]) { try{ ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream ("temp.txt")); for(int k=0;k<2;k++) { SerialApp s= new SerialApp(); s.i =20 +k; outputStream.writeObject(s); } outputStream.close(); }catch(Exception e){ System.out.println(e.toString()); } try { ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("temp.txt"));

SerialApp s = new SerialApp(); for(int k=0;k<2;k++) { s=(SerialApp)inputStream.readObject(); System.out.println(" s .i is "+s.i); } inputStream.close(); }catch(Exception e) { System.out.println(e.toString());
Copyright 2006, Tata Consultancy Services Limited (TCS).
294

Basic Programming using Java

Streams and Object Serialization

} } }
Listing 9.12 Object serialization

Consider another example in which there is a class called Book that would be used to store the details about a book. The listing given below serializes this class:
import java.io.*; class Book implements java.io.Serializable { private int bno; private String bname; private String author; Book( int a, String b, String c) { bno = a; bname = b; author = c; } void showDetails() { System.out.println("Book number : " + bno + "\nBookname : " + bname + "\nAuthor :"+ author); } }

public class SerialApp2 { public static void main (String args[]) { try{ ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("book_det.txt")); Book Lafore"); outputStream.writeObject(obj); outputStream.close(); }catch(Exception e){ obj = new Book(1,"Turbo C++", "Robert

Copyright 2006, Tata Consultancy Services Limited (TCS).

295

Basic Programming using Java

Streams and Object Serialization

System.out.println(e.toString()); } try { ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("book_det.txt")); Book obj;

obj = (Book)inputStream.readObject(); obj.showDetails(); inputStream.close(); }catch(Exception e) { System.out.println(e.toString()); } } }


Listing 9.13 Object Serialization

The output of the listing 9.13 is: Book number : 1 Bookname : Turbo C++ Author : Robert Lafore

While doing serialization you may be finding it essential to know whether a class is serializable or not, i.e., whether the class implements the Serializable interface or not. This can be done in two ways, one by looking at the API description of that class and secondly, by writing a program which tries to serialize that class. It may also be possible that the class which you are referring to in the API reference is not a documented class. That essentially makes you write a program just to test whether a class is serializable or not. Java addresses this problem and provides a tool called the serialver tool. This tool is used to find out whether the class is serializable or not and if it is serializable it displays the serialVersionUID of the class. The serialVersionUID is capable of uniquely identifying the class as it returns a unique ID of the class being serialized. This can be done by giving the following commands:
serialver Java.lang.Object The output is: Class Java.lang.Object is not serializable
296

Copyright 2006, Tata Consultancy Services Limited (TCS).

Basic Programming using Java

Streams and Object Serialization

serialver Book The output is: Book: static final long serialVersionUID = -8689733511126842292L;

9.12 Case StudyCollege Student Enrolment System (Contd.)


Once the applicant is enrolled as student, the object Student has to be serialized into a file called scollege.txt. The methods for class Student are: Create student This method initialises the attributes of the Student object. Enrol on course This method sets the value of selected coursename , optional subject and the rollnumber to the student Set name This method sets the value of name attribute Set address which will set the address attribute Given below is the code for class Student which can be serialized.
package college.student;

import java.util.Date; public class Student implements java.io.Serializable{ String studentno; String name; String address; String coursename; Date denrol; String optSub; Student(String name,String add){ this.name = name; address = add; denrol = new Date(); denrol.getDate(); } public void setName(String name){ this.name = name; } public void setAddress(String add){ address = add; }

Copyright 2006, Tata Consultancy Services Limited (TCS).

297

Basic Programming using Java

Streams and Object Serialization

public void enrolOnCourse(String cname,String stno,String osub){ coursename = cname; optSub = osub; studentno = stno; } }
Listing 9.14 Code for Student.java

Given below is the code for applet which gives the GUI for data entry of course and student details. It validates the entries and if the applicant is applicable, serializes the student details. We will now see the interaction between the classes in terms of methods invoked. The overall flow of events followed by the applet is given below :

Check qual Receive application Applicant Application Check course avail Student enroll Approve appl Course

Fig 9.1 Flow of events followed by the applet

User selects the Course, optional subject, enters name, address, result and presses the submit button. The entries are validated, in case of errors a Dialog box with appropriate message is shown. The valid entries are assigned to the applicant object which is further assigned to the application object by calling receive application method. The course entrance qualifications and the maximum number of students in a course are set by calling setEntranceQual() and setMaxStudents() respectively. The application then calls the approve application function. In case the application is approved, the student is enrolled and a Congrats message in dialog box is displayed, if the application is rejected then the dialog box displays the message you are not applicable.

package college.student; import java.awt.*;


Copyright 2006, Tata Consultancy Services Limited (TCS).
298

Basic Programming using Java

Streams and Object Serialization

import import import import import

java.awt.event.*; java.applet.*; java.awt.Choice; java.lang.*; java.io.*;

public class GCInterface extends Applet { static String ENAME ="Name cannot be Blank"; static String ECOURSE ="Course cannot be Blank"; static String EOPTSUB ="Optional Subject cannot be Blank"; static String EADD ="Address cannot be Blank"; static String ERESULT ="Result cannot be Blank"; static String VALIDFORM ="ALL CORRECT"; static String ENRANGE = "Result cannot more than 100"; Choice choiceControl1 = new Choice(); List lstSubjects = new List(); List lstOptSub = new List(); Label lblCourse = new Label("Courses"); Label lblSubjects = new Label("Core Subjects"); Label lblOptSub = new Label("Optional Subjects"); Label lblName = new Label("Enter your Name"); Label lblAdd = new Label("Address"); Label lblResult = new Label("Enter your Result"); ChangedField tfName = new ChangedField(); TextArea taAdd = new TextArea(); TextField tfRes = new TextField(10); Button btnSubmit = new Button();

//Construct the applet public GCInterface() { } //Initialize the applet public void init() { try { jbInit(); } catch (Exception e) { e.printStackTrace(); } } //Component initialization private void jbInit() throws Exception{ this.setLayout(null); this.resize(300,300);
Copyright 2006, Tata Consultancy Services Limited (TCS).
299

Basic Programming using Java

Streams and Object Serialization

choiceControl1.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(ItemEvent e) { choiceControl1_itemStateChanged(e); } }); btnSubmit.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { btnSubmit_actionPerformed(e); } });

lblCourse.setBounds(10,10,50,50); lblSubjects.setBounds(100,10,100,50); lblOptSub.setBounds(200,10,150,50); choiceControl1.setBounds(10,60,70,100); lstSubjects.setBounds(100,60,100,100); lstOptSub.setBounds(200,60,100,100); lblName.setBounds(10,180,85,20); tfName.setBounds(100,180,100,20); tfName.setMaxChars(20); tfName.setValidKeys(ChangedField.ALPHA); lblAdd.setBounds(10,230,50,20); taAdd.setBounds(100,220,200,50); lblResult.setBounds(10,280,90,20); tfRes.setBounds(110,280,50,20); btnSubmit.setBounds(150,310,50,25); btnSubmit.setLabel("Submit"); choiceControl1.addItem("MDMC"); choiceControl1.addItem("UCO"); choiceControl1.addItem("C++"); choiceControl1.setBackground(new Color(90, 112, 191)); this.add(lblCourse); this.add(lblSubjects); this.add(lblOptSub); this.add(choiceControl1); this.add(lstSubjects); this.add(lstOptSub); this.add(lblName); this.add(lblAdd); this.add(lblResult); this.add(tfName); this.add(taAdd); this.add(tfRes);
Copyright 2006, Tata Consultancy Services Limited (TCS).
300

Basic Programming using Java

Streams and Object Serialization

this.add(btnSubmit); } void choiceControl1_itemStateChanged(ItemEvent e) { showSubjects(choiceControl1.getSelectedItem()); } void btnSubmit_actionPerformed(ActionEvent e) { //validate the entries String formRes = validateForm(); if (formRes != VALIDFORM) { CreateOkDialog crt = new CreateOkDialog(formRes); System.out.println("Please reenter the form "); } else{ processForm(); } } void processForm(){ //the applet now passes interface Objects for processing String aname = tfName.getText(); String add = taAdd.getText(); String strRes = tfRes.getText(); Long res = Long.valueOf(strRes); Applicant appl1 = new Applicant(aname,add,res); Application apln1 = new Application(); apln1.rcvAppl(appl1); String strCore[] = lstSubjects.getItems(); CoreSubject core[] = CoreSubject[strCore.length]; for(int i =0;i<strCore.length; i++){ core[i] = new CoreSubject(strCore[i]); } String strOpt[] = lstOptSub.getItems(); if (strOpt.length!= 0) { OptSubject opt[] = new OptSubject[strOpt.length]; for(int i =0;i<strOpt.length; i++) opt[i] = new OptSubject(strOpt[i]); Course cs = new Course(choiceControl1.getSelectedItem() ,core, opt); cs.setEntranceQual(new Long(75)); cs.setMaxStudents(5); if (apln1.appApl(cs)){

information

to

new

Copyright 2006, Tata Consultancy Services Limited (TCS).

301

Basic Programming using Java

Streams and Object Serialization

Student Student(aname,add);

s1

new

cs.setCurrSt(); String temp = choiceControl1.getSelectedItem()+Integer.toString(cs.getCurrSt()) ; s1.enrolOnCourse(choiceControl1.getSelectedItem(),temp,lstOptSub. getSelectedItem()); CreateOkDialog crt = new CreateOkDialog("Congrats!!"); srlStudents(s1); } else{ CreateOkDialog crt = new CreateOkDialog("You are not applicable"); } } else System.out.println("str opt is zero"); } public void showSubjects(String cname){ lstSubjects.removeAll(); lstOptSub.removeAll(); if (cname == "MDMC"){ lstSubjects.addItem("c"); lstSubjects.addItem("c++"); lstSubjects.addItem("ooads"); lstSubjects.addItem("Networking"); lstSubjects.addItem("Oracle"); lstSubjects.addItem("vc"); lstSubjects.addItem("unix"); lstSubjects.addItem("vb"); // optional subjects lstOptSub.addItem("NT"); lstOptSub.addItem("JAVA"); lstOptSub.addItem("SQL"); } else if (cname == "UCO"){ lstSubjects.addItem("unix"); lstSubjects.addItem("c"); lstSubjects.addItem("oracle"); // optional subjects lstOptSub.addItem("DBA"); lstOptSub.addItem("C++"); } else if (cname == "C++"){ lstSubjects.add("c++"); // optional subjects
Copyright 2006, Tata Consultancy Services Limited (TCS).
302

Basic Programming using Java

Streams and Object Serialization

lstOptSub.addItem("OOADS"); lstOptSub.addItem("JAVA"); } } public void srlStudents(Student s) { try{ ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("scollege.txt")); outputStream.writeObject(s); outputStream.close(); }catch(Exception e){ System.out.println(e.toString()); } } public String validateForm(){ //check if course is selected if(choiceControl1.getSelectedItem() == null ) { System.out.println("Course cannot be Blank"); return ECOURSE; } //check if optional subject is selected if(lstOptSub.getSelectedItem() == null){ System.out.println("Optional Blank"); return EOPTSUB; } //check if name of student is null if(tfName.getText().trim().equals("")){ System.out.println("student name Blank"); return ENAME; } subject cannot be

cannot

be

//check if address os studemt is null if(taAdd.getText().trim().equals("")){ System.out.println("address cannot be Blank"); return EADD; } //check if res is null and does not lie between 0-100% if(tfRes.getText().trim().equals("")) return ERESULT; else { String t =tfRes.getText().trim(); long tres = Long.valueOf(t).longValue(); if( tres >100l) return ENRANGE; else{ return VALIDFORM; }
Copyright 2006, Tata Consultancy Services Limited (TCS).
303

Basic Programming using Java

Streams and Object Serialization

} } }
Listing 9.14 Interaction of Student Enrollment Systems objects in GUI interface

The html file which calls this applet is


<TITLE> College Administration -Student Enrollment </TITLE> </HEAD> <APPLET CODE = "college.student.GCInterface.class" NAME = "TestApplet" WIDTH = 350 HEIGHT HSPACE = 0 VSPACE = 0 ALIGN = middle > </APPLET> </HTML>
Listing 9.15 Html file to invoke the GCInterface applet

= 350

Fig. 9.2 Error message if address is left blank

Copyright 2006, Tata Consultancy Services Limited (TCS).

304

Basic Programming using Java

Streams and Object Serialization

Fig 9.3 Error message if the applicant does not qualify

Fig. 9.4 Message when applicant is enrolled as a student

Making your applets write to the client machine: The applet code given above is basically for a single machine. That is you run the html file which calls the applet from your browser and it displays the GUIs . The applet above takes in maximum of 5 students in course in a single run of the applet. That is the applet runs in your memory space, keeps the information of maximum number of students enrolled in your machines memory , hence in the true sense it does not emulate a client
Copyright 2006, Tata Consultancy Services Limited (TCS).
305

Basic Programming using Java

Streams and Object Serialization

server scenario in which applicants login from different machines and the number of students enrolled information is kept on the servers address space. This can be enhanced to client server application further using networking classes of Java. The above program has a statement srlStudent(s1) which serializes the s1 student object. If the applet is run on the users machine through file protocol, or run with browsers security settings as high or medium then it will throw security exception. The security exception message can be seen in the Browsers Java Console window. To see the Java Console option in the View menu options you have to enable the Java Console. Steps to enable Java Console are Select Internet Options from View menu Click on Advanced tab in the Internet Options window In the Advanced options select Java Logging Enabled option from Java VM

Fig 9.5 Internet Options window of Internet Explorer 4.0 for enabling Java Console

To avoid the security exception, your applet has to be digitally signed by a verified source like Verisign etc (for Netscape browser your applet has to implement their security classes also). For bypassing security exception in Internet Explorer you can do the following: select Internet Options from view menu select security tab from Internet Options window select custom security option

Copyright 2006, Tata Consultancy Services Limited (TCS).

306

Basic Programming using Java

Streams and Object Serialization

Fig 9.6 Internet Options window of Internet Explorer 4.0 with Custom Security Options

select settings tab on the above displayed window select Java Custom settings tab on the Security Settings window to get the window below

Copyright 2006, Tata Consultancy Services Limited (TCS).

307

Basic Programming using Java

Streams and Object Serialization

Fig. 9.7 Enabling Unsigned content checkbox in Java security options

Select edit permissions tab Click on enable option of run unsigned content and close all windows by selecting OK

For serialization to take place in the above example, put your class and html files in server web directory. For instance if it is an NT server (which is accessible by your machine) place your html files and SInterface class file in the servers Inetpub/wwwroot directory and the rest of the class files in Inetpub\wwwroot\college\student folder. Access your applet by calling the SInterface.Html file through http protocol followed by machine address or machine name and your html file name. If the student is enrolled then the student object is serialized in the scollege.txt file in the current directory of the client machine.

Before using your browser to connect to the Internet, make sure you change your security settings to high and disable receiving unsigned content. If you do not do so, you are leaving yourself open to all malicious and non malicious programs, which might be accessing your disk.

Copyright 2006, Tata Consultancy Services Limited (TCS).

308

Basic Programming using Java

Streams and Object Serialization

SUMMARY
Java provides two major classes for input output of byte streams - the InputStream class and the OutputStream Class. Apart from this there are the Reader and Writer classes, classes for object I/O etc. The InputStream class represents the basic input stream. It acts as the parent class for all other classes for input extending from it, like the FileInputStream, ByteArrayInputStream etc. The InputStream class provide some general functions, for example the read(), skip(), close() functions etc., which these sub classes use. The OutputStream class is complementary to the InputStream class. It the base class for all other classes for output that extends from it. It defines some functions for the other output stream classes. The most important function in this class is the write() function. The ByteArrayInputStream class and the ByteArrayOutputStream class is an implementation of the OutputStream class. It facilitates storing the input output in the form of a byte array which can later on be manipulated The stream-based input output to and from the files is basically performed through the classes like the FileInputStream and FileOutputStream classes. Apart from these classes, there other classes like the File class, through which you can get information about the files or the directories, The RandomAccessFile class through which you can create random access files. The filtered input output stream classes provide the basic capability to create one stream from another. This is one of the very powerful aspects of the streams because by using the filtered streams you can chain one stream to another and obtain specialized streams. Buffered streams are used to temporarily cache the data that is read from or written to the streams. It is a filter and it provides two classes the BufferedInputStream class and the BufferedOutputStream class which are used to perform buffered I/O. The DataInputStream and the DataOutputStream class are filter classes which implements the DataInput and DataOutput interfaces respectively. The DataInputStream class provides additional methods to allow primitive data types and some other types to be read as input than just in the form of bytes. Similarly, The DataOutputStream class provides additional methods for writing variables of different type to the output stream. The character streams are those types of streams which treats the streams as a stream of characters than a stream of bytes. Instead of reading byte by byte as in case of the byte streams it does the I/O with 16 bits values at a time.

Copyright 2006, Tata Consultancy Services Limited (TCS).

309

Basic Programming using Java

Streams and Object Serialization

The BufferedReader and BufferedWriter classes character streams, which are analogous to the BufferedInputStream and BufferedOutputStream classes as they too buffer the data for input output operations. Using the random access file we can write or read data at any specific location in the file. The random access file can be created using the RandomAccessFile class. Through object serialization it is possible to read or write an object to a stream as a single entity. The classes for object serialization are the ObjectInputStream and the ObjectOutputStream classes. These classes implement the ObjectInput and ObjectOutput interfaces respectively. The ObjectInput interface provides the readObject() method to read objects from the stream and the ObjectOutput interface has the writeObject() method to write objects to the stream. To find out whether a class is serializable or not you can use the serialver tool.

Copyright 2006, Tata Consultancy Services Limited (TCS).

310

Basic Programming using Java

Streams and Object Serialization

SELF ASSESSMENT
Q1) Fill in the blanks: 1. ------------ and ------------ are the modes are defined for the RandomAccessFile class. 2. The DataInputStream is a filter class, it requires ------------ as an argument for its creation. 3. The ObjectInputStream and the ObjectOutputStream classes implement -----------and ------------ interfaces. 4. The InputStream class file provides some basic methods for I/O like ------------, -----------, ------------. 5. The concept of filters allow the ------------ of one class with another. Q2) State true or false: 1. The File class can show the attributes of a specific file or directory. 2. The object that is to be serialized must implement Serializable interface. 3. The read() method throws EOFException. 4. The ByteArrayOutputStream class is a filter class. 5. The System.out is an object of the InputStream class. Q3) Explain the concept of streams. What are the various categories of streams? Describe briefly about each one of them. Q4) What is the BufferedReader class? What is it used for? Q5) What are the various methods present in the RandomAccessFile class? Write down the utility of each one of them Q6) What is object serialization? What is its significance?

Copyright 2006, Tata Consultancy Services Limited (TCS).

311

Basic Programming using Java

Streams and Object Serialization

LAB EXERCISE
1. Create a file stream which writes to a file called parts.dat . This file contains the details of a part like the partcode - int, qty_avail - int, rate - float. After writing to the file it displays the contents of the file. 2. Take any file of your file system or find out whether it contains some bytes. If it is not empty, read and display its contents using the buffered streams. 3. Accept a directory name as a string from the user and validate whether the string is a directory or not. If it is a directory, then display the list of files and directories under it distinguishing the files and directories by giving a remark along with their names. 4. Create a random file called salesman.txt that stores the, salesmanID - int and the compensation - float, given to a particular salesman. Display the record of a particular salesman. 5. Create a class called Orders that has the following elements: Data Members order_No - char invoice_Number - int order_Description - char order_Quantity - float Member Functions getDetails() showDetails() Serialize this class, add some order details and store in a file called orders.txt . After that print the order details. 6. Continuing with case study in session 8 handle the event for button Save Form. For Employee Information sheet save the form objects in employee.txt file and clear the screen. For Provident Fund save the form objects in pf.txt file and clear the screen. Additional Exercise 7. Provide button Admission List in SInterface.java which when clicked on displays details of the student (that is selected applicants) with their Student roll number, CourseName and optional subject. 8. Modify class CreateOkDialog so that the along with the message to be displayed the window name can also be passed at run time.

Copyright 2006, Tata Consultancy Services Limited (TCS).

312