StreamsSummary

advertisement
Programming (Java)
Streams, Readers and Writers
Streams, Readers and Writers
C. Horstmann, Big Java, Ch 15 is an excellent chapter about Streams. These notes pick out a
few essentials to show "how to do..." common tasks in reading and writing files.
The jave.io.* package defines a framework of I/O classes. The roots of the hierarchies are
 InputStream, and OutputStream for byte-by-byte reading and writing,
 Reader and Writer for reading and writing characters.
Some Classes in java.io
InputStream, OutputStream
FileInputStream, FileOutputStream
ObjectInputStream, ObjectOutputStream
Reader, Writer
FileReader, FileWriter
BufferedReader
PrintWriter
Comment
read/write a byte
read/write bytes from/to a file
read/write serialized objects
read/write characters
read/write character from/to a text file
reads a line of text from a file into a String
print() methods for all types to output as text
The basic methods of Streams are to read and write one byte of data, and for Readers and
Writers to read and write one character of text. Sub-classes provide utility methods that read
and write more convenient structures, e.g. Arrays of bytes, Strings, and Objects.
Associating a file with an I/O stream
FileInputStream
and FileOutputStream have constructors that take a filename as a
parameter. This sets up reading and writing to a named file. Similarly FileReader and
FileWriter may be used to associate text streams with named files.
FileInputStream infile = new FileInputStream("somefile.dat");
FileOutputStream outfile = new FileOutputStream("datafile.dat");
FileWriter out = new FileWriter("out.txt");
The java.io classes provide high level I/O methods by using the 'decorator' pattern. Classes
add functionality to other classes by 'wrapping' them. For example a BufferedReader can
take a FileReader as a parameter. This enables text files to be read efficient line by line from
a file using the readLine() method of BufferedReader.
BufferedReader in = new BufferedReader(new FileReader("mytext.txt"));
String str = in.readLine(); //read first line into a String
while (str!=null) {
//null signals end of file
...process str...
//process the current string
str = in.readLine();
//get the next line
}
in.close();
//close the file
This is the classic algorithm structure for file processing. Note that in Java we have to try to
read ahead. If the read fails, then this signals that the end of file has been reached.
Similarly text can be sent to an output file by wrapping a FileWriter with a PrintWriter.
PrintWriter out = new PrintWriter(new FileWriter("report.txt"));
dmu/lz/oct03
1
Programming (Java)
Streams, Readers and Writers
The PrintWriter class has print() and println() methods for every primitive type and for
Objects. These methods format the primitive type into characters, and in the case of Object it
outputs the text returned by the object's toString() method.
Example: to output each item in an ArrayList, list, on a separate line. We make use of the
ArrayList's iterator method to access each item sequentially.
PrintWriter out = new PrintWriter(new FileWriter("report.txt"));
Iterator iter = list.iterator();
while (iter.hasNext()) {
out.println(iter.next());
}
out.flush();
//ensure output buffers are emptied
out.close();
//close the file when finished
Operating systems tend to buffer output into larger sized blocks before writing to disk. The
flush() command forces the buffers to be written. Always close() the file when finished.
Reading and Writing Objects
Java provides two very powerful classes to read and write objects. The ObjectOutputStream
and the ObjectInputStream, with methods readObject() and writeObject() respectively.
public final Object readObject() throws ClassNotFoundException, IOException
public final void writeObject() throws IOException
Only objects that implement the java.io.Serializable interface can be written or read
using these methods. The Serializable interface has no methods; it only acts a flag to indicate
that a class may be serialized.
The usual way to save data for an application is to wrap it up in one object and then save that
object. Example: the code to save an object, myObject, to a file called "data.obj" is as
follows:
ObjectOutputStream out =
new ObjectOutputStream( new FileOutputStream("data.obj") );
out.writeObject(myObject);
out.close();
Reading the object back is also one line of code. The readObject() method returns an
Object. This has to be cast to the object's type.
ObjectInputStream in =
new ObjectInputStream( new FileInputStream("data.obj") );
ObjectType obj = (ObjectType) in.readObject();
in.close();
Exceptions
I/O methods are always prone to failure, e.g. file does not exist, or a file is closed, or disk
fault. Therefore most code that does any I/O is usually wrapped in a try..catch statement.
Alternatively, the method header carries the appropriate throws clause to delegate the error
higher up the method call stack.
The most common exceptions are IOException, and ClassNotFoundException when using
the readObject() method.
dmu/lz/oct03
2
Programming (Java)
Streams, Readers and Writers
The class below wraps the object i/o code into two utility methods.
/* CSCI2014
* An Object file save and load utility.
* Provides convenience class methods to:
*
- save an object to a named file
*
- load an object from a named file
* The Object must be Serializable.
*
* @author lz
* @version oct 03
*/
import java.io.*;
class ObjectFileUtility {
/* Writes an object to the named file. */
public static void saveObject(Serializable obj, String filename)
throws IOException
{
ObjectOutputStream oos =
new ObjectOutputStream( new FileOutputStream(filename) );
oos.writeObject(obj);
oos.flush();
oos.close();
}
/* Returns the object saved in filename.
* Hides some of the exception handling by re-throwing any
* ClassNotFoundException as an IOException.
*/
public static Object loadObject(String filename) throws IOException
{
ObjectInputStream ois =
new ObjectInputStream(
new FileInputStream(filename)
);
try
{
Object obj = ois.readObject();
ois.close();
return obj;
}
catch (ClassNotFoundException e) {
throw new IOException("ClassNotFoundException");
}
}
}
The example programs below demonstrate how this utility may be used to save and load an
AppointmentDiary object (refer to Exercises 1 and 2).
Note that the class headers for both Appointment and AppointmentDiary need to include the
clause implements java.io.Serializable.
dmu/lz/oct03
3
Programming (Java)
Streams, Readers and Writers
class Appointment implements java.io.Serializable {
private String name; //name of person to meet
private int time;
//appointment time
... as before ...
}
import java.util.*;
class AppointmentDiary implements java.io.Serializable {
private String owner;
private ArrayList diary;
//the diary owner's id
//the appointment collection object
//Constructor
public AppointmentDiary(String owner) {
this.owner = owner;
diary =new ArrayList();
}
public void addAppointment(Appointment apt) {
diary.add(apt);
}
public void cancelAppointmentAt(int time) {
Appointment apt = this.getAppointmentAt(time);
diary.remove(apt);
}
public Appointment getAppointmentAt(int time) {
Appointment apt = null;
boolean found = false;
Iterator iter = diary.iterator();
while (iter.hasNext()&& !found) {
apt = (Appointment) iter.next();
if (apt.getTime() == time)
found = true;
}
return found ? apt : null; //null if not found
}
public String toString() {
return "Diary for " + owner + ":\n " + diary;
}
}
dmu/lz/oct03
4
Programming (Java)
Streams, Readers and Writers
This program creates an AppointmentDairy, populates it with a few appointment objects, and
then saves all the data to file. When the AppointmentDiary is saved, all of its attributes are
serialized to file: this includes the collection of appointment objects.
/* CSCI2014
* Author: lz, oct 2003
* Program to test saving an AppointmentDiary to a file
*/
class DiarySaveTest {
public static void main(String[] arg) {
AppointmentDiary diary = new AppointmentDiary("The Boss");
diary.addAppointment(new Appointment("fred", 1130));
diary.addAppointment(new Appointment("ali", 1320));
diary.addAppointment(new Appointment("jim", 1030));
diary.addAppointment(new Appointment("mary", 1215));
diary.addAppointment(new Appointment("rio", 900));
diary.addAppointment(new Appointment("mary", 1500));
System.out.println(diary);
try {
ObjectFileUtility.saveObject(diary, "AppointmentDiary.object");
System.out.println("AppointmentDiary saved.");
}
catch (java.io.IOException e) {
System.out.println("Save failed. " + e.getMessage());
}
}
}
The following program can be run after the DiarySaveTest program. It demonstrates how the
previously saved AppointmentDiary may be reloaded into memory again. The I/O section is
written within a try..catch statement in order to trap the declared exceptions.
/* CSCI2014
* Author: lz, oct 2003
* Program to load a previously saved AppointmentDiary object.
*/
class DiaryLoadTest {
public static void main(String[] arg) {
AppointmentDiary aDiary = null;
try {
Object obj;
obj = ObjectFileUtility.loadObject("AppointmentDiary.object");
aDiary = (AppointmentDiary) obj;
}
catch (java.io.IOException e) {
System.out.println("Load failed. " + e.getMessage());
}
System.out.println(aDiary);
}
}
dmu/lz/oct03
5
Download