28
Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

  • View
    220

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Java I/O classes –case study in an OO library

Flexible and somewhat slick, but a bit of a mess (though improving)

Page 2: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Java classes for doing i/o• Includes file i/o, memory i/o, socket i/o, inter-process

(pipes), etc.• All stored in package java.io• Excellent example of OO design

– Very general and scaleable

• Unfortunately, also obfuscates simple tasks.• How to proceed

– Understand basic design– Create some libraries to do common tasks

• Goal is not to be exhaustive but rather understand how to do basic operations AND understand the OO structure of this library (ie a good case study).

Page 3: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

InputStream/OutputStream

• Start by studying the java.io.InputStream and java.io.OutputStream API

• These are base class for performing all binary byte-based i/o

• Note that these classes are abstract each with a single abstract method– abstract int read()– abstract void write(int)

• Concrete subclasses must provide implementation of read/write that can get/put a single byte to/from the relevant source

Page 4: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Concrete subclasses of InputStream/OutputStream

• Since InputStream/OutputStream are abstract, they cannot be used to create objects (of course, they can be used for typing).

• A very common non-abstract subclass is FileOutputStream/FileInputStream.

• These can be used in a simple way to do the most basic byte-based file io

• Other classes for byte-based i/o (sockets, pipes, memory, etc.) behave similarly. File is just the easiest to use to demonstrate the main concepts.

Page 5: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Example with FileInputStream

/* class example DataInput1.java *//* assumes each char is one byte – dangerous (why?) import java.io.FileInputStream;public class DataInput1{ public static void main(String[] args) throws Exception{ String file = args[0]; int input; FileInputStream fin = new FileInputStream(file); while ( (input = fin.read()) != -1){ System.out.print((char) input); } }}

Page 6: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Example with FileOutputStream

/* class example DataOutput1.java *//* assumes each char is a single byte */import java.io.FileOutputStream;public class DataOutput1{ public static void main(String[] args) throws Exception{ String file = args[0]; String output = "Hello World"; FileOutputStream fout = new FileOutputStream(file); char[] outputAsChars = output.toCharArray();

for (int i = 0; i < outputAsChars.length; ++i) fout.write(outputAsChars[i]); fout.close(); }}

Page 7: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;

public class CopyBytes { public static void main(String[] args) throws IOException {

FileInputStream in = null;FileOutputStream out = null;try {

in = new FileInputStream("xanadu.txt"); out = new FileOutputStream("outagain.txt"); int c; while ((c = in.read()) != -1) { out.write(c); } } finally { if (in != null) { in.close(); } if (out != null) {

out.close(); }

} }}

Another Example Combining both

Page 8: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Reader/Writer• Java maintains a second class hierarchy for

performing higher-level character-based i/o.

• These automatically convert to native character stream – Often this is 8-byte based but not always– Handled for you by Reader/Writer

• The two base classes in this case are– java.io.Reader – java.io.Writer

• Very similar to InputStream/OutputStream there is a concrete set of classes FileReader and FileWriter

Page 9: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;

public class CopyCharacters { public static void main(String[] args) throws IOException {

FileReader inputStream = null;FileWriter outputStream = null;try {

inputStream = new FileReader("xanadu.txt"); outputStream = new FileWriter("characteroutput.txt");

int c; while ((c = inputStream.read()) != -1) {

outputStream.write(c); }

//….

c now storesa 2-byte value

Page 10: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Better: can do String-based i/o

/* example Writer1.java in course examples *//* using a simple FileWriter for String-based i/o */

import java.io.FileWriter;public class Writer1{ public static void main(String[] args) throws Exception{ String file = args[0]; String output = "Hello World!"; FileWriter fw = new FileWriter(file); fw.write(output); fw.close(); }}

Page 11: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Can do line-based i/o (see also java.util.Scanner)

import java.io.BufferedReader;import java.io.InputStreamReader;public class Reader1{ public static void main(String[] args) throws Exception{ /* convert System.in, which is an InputStream, to a Reader by wrapping in InputStreamReader, then wrap everything in BufferedReader */ String input; BufferedReader bin = new BufferedReader (new InputStreamReader (System.in)); while ( (input = bin.readLine()) != null){ System.out.println("you typed " + input); }}}

converts anInputStreamto a Reader

Page 12: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Higher-level functionality• FileInputStream/FileOuputStream and

FileReader/FileWriter allow you to do pretty much any file i/o at a very low level.

• However, this is too low-level for Java.

• Java provides many more libraries to read/write higher-level constructs:– characters– Strings– native datatypes– arrays – arbitrary objects (serialization)

Page 13: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

“Decorator” Pattern• These capabilities are added using a design

called the Decorator Pattern.

• InputStream/OutputStream instances are passed to a wrapper or decorator class that uses them and adds to their functionality.

• For example, floating point numbers can be read from a file by chaining together a FileInputStream and another class that assembles bytes into portable floating point.

Page 14: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Purpose of Decorator

• Best way to think of this is as follows:– There are two important issues when constructing an i/o

library• Where the i/o is going (file, etc).

• How the data is represented (String, native type, etc.)

– Rather than create a class for each combination, Decorator classes allow you to mix and match, augment functionality of base classes.

– This is a bit confusing but is very flexible.– Decotators can also add other capabilities, such as peek

ahead, push back, write line number, etc.

Page 15: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Java i/o Decorator Classes

• All Java i/o decorator classes inherit from FilterInputStream and FilterOutputStream

• Look at the api for these classes and note a few things:– They wrap instances of InputStream/OutputStream

respectively.– They inherit from InputStream/OutputStream respectively

• This is an odd inheritence hierarchy but is necessary to ensure that the FilterStreams support the same interface as the underlying class.

Page 16: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Filter Streams• Easiest way to think of the filter streams as

wrapping an underlying class which they augment the functionality of.

Consider the respective constructors– FilterInputStream(InputStream in);– FilterOutputStream(OutputStream out);

• In each case, the FilterStreams use an underlying presumably simpler inputstream and augment its functionality.

Page 17: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Some FilterStream examples to clarify this

• Perhaps most common FilterInputStream is DataInputStream.

• Study the API and be sure you understand the inheritance hierarchy

• DataInputStream stores an InputStream and uses this to do higher-level i/o– readInt, readDouble, etc.

• DataOutputStream is analogous

Page 18: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Example of DataInputStream/* DataInputStream2 example in course examples */import java.io.DataOutputStream;import java.io.FileOutputStream;

public class DataOutput2{ public static void main(String[] args) throws Exception{ String file = args[0]; double[] data = {1.1,1.2,1.3,1.4,1.5}; DataOutputStream dout = new DataOutputStream (new FileOutputStream(file));

for (int i = 0; i < data.length; ++i){ dout.writeDouble(data[i]); } dout.close();}}

Page 19: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Example of DataInputStream/* DataOutput2 example in course examples */import java.io.DataInputStream;import java.io.FileInputStream;import java.io.EOFException;public class DataInput2{ public static void main(String[] args) throws Exception{ String file = args[0]; DataInputStream din = new DataInputStream(new FileInputStream(file)); double data; try{ while (true){ data = din.readDouble(); System.out.println(data); } } catch (EOFException eofe){} din.close();}}

Page 20: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Other Decorators

• Another common set of decorator classes is BufferedInputStream and BufferedOutputStream.

• Note that java.util.Scanner is a new and simpler alternative for a lot of high-level parsing tasks.

• These augment the functionality of the underlying stream by providing system buffering for higher-performance i/o

• They also add support for the mark method.

• Examples on next slide (notice how these classes can be multiply chained together in various ways.

Page 21: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

BufferedInputStream Example

import java.io.*; /public class DataInput3{ public static void main(String[] args) throws Exception{ String file = args[0]; DataInputStream din = new DataInputStream (new BufferedInputStream (new FileInputStream(file))); double data; /* need an exception to know when end of file is hit */ try{ while (true){ data = din.readDouble(); System.out.println(data); } } catch (EOFException eofe){} din.close();}}

Page 22: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

BufferedOutputStream example

import java.io.BufferedOutputStream;import java.io.DataOutputStream;import java.io.FileOutputStream;

public class DataOutput3{

public static void main(String[] args) throws Exception{ String file = args[0]; double[] data = {1.1,1.2,1.3,1.4,1.5}; DataOutputStream dout = new DataOutputStream (new BufferedOutputStream (new FileOutputStream(file)));

for (int i = 0; i < data.length; ++i){ dout.writeDouble(data[i]); } dout.close();}}

Page 23: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Other output streams

• FileOutputStream is probably the most common.• However, note that we could replace

FileOutputStream with another Outputstream in these examples.

• In that case, the same decorated or undecorated data would be sent to some other device.

• Good example of this is thread communicatoin, memory i/o, and socket i/o (using Socket class).

• I strongly encourage you to familiarize yourself with these classes.

Page 24: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Serialization

• Objects can be written to streams also. This process is known as serialization.

• This is a huge convenience compared with having to marshal and unmarshal iv’s.

• But the issue is even deeper – how are methods represented, objects that contain objects as iv’s, etc.

• Java takes care of all of this with a very nice serialization interface.

Page 25: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Serialization classes

• Relevant classes– java.io.ObjectInputStream – java.io.ObjectOutputStream

• Note that these required an underlying Input/OutputStream to do their work.

• For a class to be serializable, it also must implement the Serializable interface (no methods).

• Finally, a class-scope variable can be declared as transient, meaning that it is ignored during serialization.

Page 26: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Serialization Example/* simple example of Serialization -- writing an object directly to an OutputStream without having to marshal and unmarshal */import java.io.*;public class Serialization{ public static void main(String[] args) throws Exception{ String flag = args[0]; String file = args[1]; Currency c = new Currency("US Dollar", "USD“, 10, 5); Currency d; if (flag.equals("-w")){ ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(new File(file))); out.writeObject(c); } else if (flag.equals("-r")){ ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File(file))); System.out.println("Reading serialized object"); d = (Currency) in.readObject(); }}}

Page 27: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Related Topics• java.nio (“new io”) classes for file io are now

standard as of J2SE. Will go over a bit final week, but aren’t in common use yet.

• java.io.File class– Very nice. Many methods for portably manipulating

files• java.io.Socket class

– Provides Input/OutputStreams for communication across ports of different computers

• PrintWriter class (e.g. println method)• Writing zip files, jar files, etc.• java rmi: Remote Method Invocation:

– DO’s on top of serialization

Page 28: Java I/O classes – case study in an OO library Flexible and somewhat slick, but a bit of a mess (though improving)

Suggested Readings

• Eckel’s detailed section on i/o

• Patterns in Java, A Catalog of Reusable Design Patterns Illustratred with UML, Mark Grand, Wiley Press.

• Design Patterns, Elements of Reusable Object-Oriented Software, Gamma et al.