COMP201 Java Programming

Download Report

Transcript COMP201 Java Programming

COMP201 Java Programming
Topic 6: Streams and Files
Reading: Chapter 12
COMP201 Topic 6 / Slide 2
Outline

Introduction and overview

Writing and reading text files

Writing and reading binary files

Writing and reading objects

File management
COMP201 Topic 6 / Slide 3
Introduction and Overview

When talking about IO, we need to consider files

Location:
– blocks of main memory
– local file system
– over the net

Format:
– text or binary
– zipped or not zipped

Access mode:
–
–
–
–

plain sequential,
buffered,
pushback,
Random
Java has classes for all possible combinations.
COMP201 Topic 6 / Slide 4
Introduction and Overview

Java streams provide an abstraction of files at different locations:
Local files and files from the net are handled in essentially the same way.
In this lecture, we deal with only files on local machine.

Java has many (60+) stream classes for various file formats and
access modes

We will cover only a few commonly used classes.

What follows is an overview of those 60+ classes.




Classes for reading text files
Classes for writing text files
Classes for reading binary files
Classes for writing binary files
COMP201 Topic 6 / Slide 5
Reader


All classes for reading from text files descend from the abstract
class Reader
Reader has an method read, which returns the next unicode
character or –1 (EOF)
Reader
CharArray
Reader
InputStream
Reader
File
Reader
Piped
Reader
Filter
Reader
Pushback
Reader
String
Reader
Buffered
Reader
LineNumber
Reader
COMP201 Topic 6 / Slide 6
Writer


All classes for writing to text files descend from the abstract class
Writer
Writer has an method write(int b), which writes a
unicode character to an output
Writer
CharArray
Filter
Writer
Writer
OutputStream
Writer
File
Writer
String
Writer
Print
Writer
Piped
Writer
Buffered
Writer
COMP201 Topic 6 / Slide 7
InputStream


All classes for reading from binary files descend from the
abstract class InputStream
InputStream has one abstract method read, which returns
the next byte character or –1 (EOF)
InputStream
ByteArray
Object
Piped
StringBuffer
InputStream InputStream InputStream
InputStream
File
Filter
Sequence
InputStream
InputStream
InputStream
....
Buffered
InputStream
Data
InputStream
LineNumber
InputStream
Pushback
InputStream
COMP201 Topic 6 / Slide 8
OutputStream


All classes for writing to binary files descend from abstract class
OutputStream
OutputStream has one abstract method write(int b),
which writes one byte to an output
OutputStream
ByteArray
File
Piped
OutputStream
OutputStream
OutputStream
Object
Filter
OutputStream
OutputStream
....
Buffered
Data
OutputStream OutputStream
PrintStream
Checked
OutputStream
COMP201 Topic 6 / Slide 9
Writing Text Output

Writing to a text file:

Open a file for writing
FileWriter f = new FileWriter(“employee.dat”);

The FileWriter class has method, namely write, for writing
contents of stream f to file “employee.dat”.

But it has no methods for putting information into the stream.

Solution: nest FileWriter with PrintWriter
PrintWriter out = new PrintWriter(f);

Now you can use methods of PrintWriter
out.print(…), out.println(…)//DataFileTest.java
COMP201 Topic 6 / Slide 10
Writing Text Output



1.
2.
3.
Java uses Unicode characters: 2 bytes for each character.
User’s system might use a different encoding. E.g. Windows
uses ISO 8859-1, i.e. ANSI code.
Potential mismatch automatically dealt with by FileWriter
To be more precise, FileWriter is a combination of
OutputStreamWriter and FileOutputStream.
FileWriter f = new FileWriter(“employee.dat”);
is equivalent to
OutputStreamWriter f = new
OutputStreamWriter( new
FileOutputStream(“employee.dat”));
OutputStreamWriter resolves the potential mismatch.
User can choose other encoding using
new OutputStreamWriter(OutputStream, “Big5”)
COMP201 Topic 6 / Slide 11
Writing Text Output
More Notes:

Attempts to write to a file might result in IOException
when, e.g., file system full or no write permission. As such,
one needs deal with exceptions(either use the try/catch
blocks or throw).

PrintWriters are always buffered.
close stream after use to flush out the the last bits.
Can manually flush buffer using the flush method.
Import java.io.*.




System.out is a predefined OutputStreamWriter,
stands for screen.
COMP201 Topic 6 / Slide 12
Writing Text Output
public void writeData(PrintWriter out) throws
IOException
{
GregorianCalendar calendar = new
GregorianCalendar();
calendar.setTime(hireDay);
out.println(name + "|"
+ salary + "|"
+ calendar.get(Calendar.YEAR) + "|"
+ (calendar.get(Calendar.MONTH) + 1) + "|"
+ calendar.get(Calendar.DAY_OF_MONTH));
}
COMP201 Topic 6 / Slide 13
Reading Text Input

Reading a text file:

Open a file for reading
FileReader f = new FileReader(“employee.dat”);

Nest FileReader with BufferedReader so that you can
extract information from stream f.
BufferedReader in = new BufferedReader(f);

Now you can read lines in input as strings
in.readLine();

Might throw IOException.
DataFileTest.java
COMP201 Topic 6 / Slide 14
Reading Text Input

Reading a text file / Parsing input

s = readLine() gives you a long string.

Need to break the string into individual strings and convert
them into proper type.

To do this, use the StringTokenizer class in java.util.
Create a StringTokenizer object for the delimiter “|”
StringTokenizer t = new StringTokenizer(s, “|”);

COMP201 Topic 6 / Slide 15
Reading Text Input

Reading a text file / Parsing input
 Use the nextToken method to extract the next piece from
string.
t.nextToken() --- name.
t.nextToken() --- salary as string. Needs Double.parseDouble
t.nextToken() --- year as string. Needs Integer.parseInt
t.nextToken() --- month as string. Needs Integer.parseInt
t.nextToken() --- day as string. Needs Integer.parseInt


Here we know that there are 5 tokens on each line.
In general, call t.hasMoreTokens before each
t.nextToken
DataFileTest.java
COMP201 Topic 6 / Slide 16
Reading Text Input
public void readData(BufferedReader in) throws
IOException
{
String s = in.readLine();
StringTokenizer t = new StringTokenizer(s, "|");
name = t.nextToken();
salary = Double.parseDouble(t.nextToken());
int y = Integer.parseInt(t.nextToken());
int m = Integer.parseInt(t.nextToken());
int d = Integer.parseInt(t.nextToken());
GregorianCalendar calendar
= new GregorianCalendar(y, m - 1, d);
// GregorianCalendar uses 0 = January
hireDay = calendar.getTime();
} //DataFileTest.java
COMP201 Topic 6 / Slide 17
Reading From the Keyboard
System.in is a predefined InputStreamReader, stands for
keyboard.
import java.io.*;
public class Echo {
public static void main(String[] args)
throws IOException {
BufferedReader in =
new BufferedReader(
new InputStreamReader(System.in));
String s;
while((s = in.readLine()).length() != 0)
System.out.println(s);
// An empty line terminates the program
}
} //Echo.java
COMP201 Topic 6 / Slide 18
Writing Binary Files


Open a binary file for writing
FileOutputStream out =
new FileOutputStream(“employee.dat”);
Writing to a binary file
byte b = 0;
out.write( b ); // write a byte appears as 00

Writing to a binary file
out.write(int b);
Writes the specified byte to this output stream.
The general contract for write is that one byte
is written to the output stream. The byte to be written
is the eight low-order bits of the
argument b. The 24 high-order bits of b are ignored.
-- JDK 1.3 --
COMP201 Topic 6 / Slide 19
Writing Binary Files

Suppose we want to write double, int, string, etc… to a binary
file in buffered mode.

Open binary file for writing as follows:
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream("employee.dat")));

Now we can write simply using:
out.writeChars( name + "\n" );
out.writeDouble(salary);
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(hireDay);
out.writeInt(calendar.get(Calendar.YEAR));
out.writeInt(calendar.get(Calendar.MONTH) + 1);
out.writeInt(calendar.get(Calendar.DAY_OF_MONTH));
//BinaryFileTest.java
COMP201 Topic 6 / Slide 20
Reading Binary Files

Open a binary file for reading
FileInputStream in =
new FileInputStream(“employee.dat”);
byte c = in.read();

// read a byte
Reading from a binary file
int in.read();
Reads the next byte of data from the input stream. The value byte is returned
as an int in the range 0 to 255. If no byte is available because the end of the
stream has been reached, the value -1 is returned. -- JDK 1.3 –

Programs seldom read and write bytes. Combine with subclasses of
FilterInputStream and FilterOutputStream (see slides 7
and 8) to construct desired streams.
COMP201 Topic 6 / Slide 21
Reading Binary Files

To read double, int, string, etc … from a binary file in buffered
mode, open binary file for reading as follows:
DataInputStream in = new DataInputStream(
new BufferedInputStream(
new FileInputStream("employee.dat")));

Now we can read by using:
name = in.readLine()
salary = in.readDouble();
int y = in.readInt();
int m = in.readInt();
int d = in.readInt();
GregorianCalendar calendar=new GregorianCalendar(y, m - 1,d);
hireDay = calendar.getTime();
//BinaryFileTest.java
//No need for StringTokenizer
COMP201 Topic 6 / Slide 22
Writing and Reading Objects

Tedious to do manually.

Java provides a mechanism called object serialization that makes this
straightforward.

To save and read objects of a class, the class must implement the
Serializable interface.
class Employee implements Serializable { ….}

Serializable has no methods. It is just a tag.

Not all classes are made serializable for security reasons.(P742)
COMP201 Topic 6 / Slide 23
Writing Objects

To save an object, open an ObjectOutputStream
ObjectOutputStream out =
new ObjectOutputStream (
new FileOutputStream(“employee.dat”));

Simply use writeObject method to save an object
Employee harry = new Employee("Harry Hacker", 35000,
1989,10,1);
Manager carl = new Manager("Carl Cracker", 75000,
1987,12,15);
out.writeObject(harry);
If a superclass implements
out.writeObject(carl);
Serializable, a subclass does
this automatically.
COMP201 Topic 6 / Slide 24
Reading Objects

To get back an object, open an ObjectInputStream
ObjectInputStream in = new ObjectInputStream (
new FileInputStream(“employee.dat”));

Use readObject method to retrieve objects in the same order in
which they were written
Employee[] newStaff = (Employee[]) in.readObject();
Cast necessary because readObject returns an object of class
Object.


Strings and arrays can be handled this way since they are objects
//ObjectFileTest.java
COMP201 Topic 6 / Slide 25
Writing and Reading Objects

The above scheme works even when objects have reference field.

Example:
carl
tony
class Manager extend Employee
{ …
secretary
secretary
private Employee secretary;
}
Employee harry = new Employee( …);
Manager carl = new Manager(…);
carl.setSecretary(harry);
Manager tony = new Manager(…);
harry
tony.setSecretary(harry);
COMP201 Topic 6 / Slide 26
Writing and Reading Objects

The following does not save three copies of harry
out.writeObject(carl);
out.writeObject(harry);
out.writeObject(tony);

Here is what really happens:





Each object gets a unique serial number (1, 2, ..)
When saving an object, find out whether the same object has
already been stored.
If yes, just write “same as previously saved object with serial
number x”.
Reading reverse the procedure.
All these are done automatically.
//ObjectRefTest.java
COMP201 Topic 6 / Slide 27
A Diversion/Using serialization for cloning


Idea

Write an object to an output stream
out.writeObject(someObeject)

Read it back in
copy = in.readObject()
Note: No need to write the object to a file. Write it to a byte array (an
internal buffer) using ByteArrayOutputStream
COMP201 Topic 6 / Slide 28
A Diversion/Using serialization for cloning
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream out= new ObjectOutputStream(bout);
out.writeObject(someObject);
out.close();
// read a clone of the object from the byte array
ByteArrayInputStream bin = new
ByteArrayInputStream(bout.toByteArray());
ObjectInputStream in = new ObjectInputStream(bin);
Object copyOfObject = in.readObject();
in.close();
//SerialCloneTest.java
bout.toByteArray(): creates
byte array and copy contents over
COMP201 Topic 6 / Slide 29
File Management

Use java.io.File:



A File object can represent either a file or a directory. Use the
isDirectory and isFile methods to find out.
Creating a new directory:
1.
Create a File object
1. File tempDir = new File( “temp”);
2.
Make it a directory
1. tempDir.mkdir();
Inspecting contents of a directory
tempDir.list() returns an array of file names under the
directory
COMP201 Topic 6 / Slide 30
File Management

Creating a new file
1.
2.

Create a File object:
File foo = new File(“dirName”+File.separator +
“data.txt”);
File foo = new File(“dirName”, “data.txt”);
Create file
1. foo.createNewFile(): creates a file if no file with that
name exists;
Deleting files and directories
someDir.delete();
someFile.delete();
//FindDirectories.java