Stream and File I/O in Java - clear

advertisement
Streams and File I/O in Java
Eric Allen
Rice University
Streams and Lazy Evaluation
• Java I/O is based on the notion of streams
• Streams are sequences of data (whose
elements may be computed on demand)
• Streams originated from functional
programming, as an alternative to mutation
A Very Simple Stream
class OneStream extends IntStream { public int next() { return 1; } }
A Slightly More Complex Stream
public class NatStream {
private int current = 0;
public int next() {
return current++;
}
}
Streams And Computation
• Streams can be composed and filtered to
produce more complex streams
• Let’s apply the Union, Composite, and
Command Patterns to construct composable
streams of ints…
IntStream
NatStream
ComposableIntStream
abstract class IntStream {
public abstract int next();
}
class NatStream extends IntStream {
private int current = 0;
public int next() { return current++; }
}
abstract class ComposableIntStream extends IntStream {
private Operator op;
private IntStream left;
private IntStream right;
public ComposableIntStream(Operator _op,
IntStream _left,
IntStream _right)
{
op = _op;
left = _left;
right = _right;
}
public int next() { return op.apply(left.next(), right.next()); }
}
abstract class Operator {
public abstract int apply(int left, int right);
}
// for example,
class Adder extends Operator {
public int apply(int left, int right) { return left + right; }
}
// and
class Multiplier extends Operator {
public int apply(int left, int right) { return left * right; }
}
Now we can construct all sorts of
nifty composable IntStreams:
class EvenStream extends ComposableIntStream {
public EvenStream() {
super(new Adder(), new NatStream(), new NatStream()); }
}
class SquareStream extends ComposableIntStream {
public SquareStream() {
super(new Multiplier(), new NatStream(), new NatStream()); }
}
Building the Natural Numbers
class ZeroStream extends IntStream { public int next() { return 0; } }
class AdderStream extends ComposableIntStream {
public AdderStream(IntStream left, IntStream right) {
super(new Adder(), left, right);
}
}
Building the Natural Numbers
class AlternateNatStream extends IntStream {
IntStream value = new ZeroStream();
public int next() {
value = new AdderStream(new OneStream(), value);
return value.next();
}
}
In fact, streams can be used as a
foundation for all of number
theory!
• Exercise (optional/not for credit): Extend
IntStreams to include a stream of prime
numbers
• Hint: define the notion of filtered streams,
as a subtype of ComposableIntStreams
Applications of Streams
• Streams are natural models of many realworld systems:
–
–
–
–
Stock prices
Mouse/keyboard/monitor input
Radio signals
Human input to a program (DrJava
interactions)
– Contents of a file
Output Streams Model Systems
That Take Input
• Just as we can read from sources, we can
write to destinations
• Output streams take input as it’s computed
I/O Streams in Java
• java.io.InputStream, java.io.OutputStream
• Readers, writers are adapters to streams, to
make certain sorts of I/O easier
Reading from a File
> FileReader fReader = new FileReader(fn);
> fReader.read()
97
> (char)fReader.read()
b
Writing to a File
> FileWriter fWriter = new FileWriter(fn);
> fWriter.write()
Testing Writers
• Readers/Writers can be composed using
PipedReaders and PipedWriters
PipedReader pReader = new PipedReader();
PipedWriter pWriter = new PipedWriter(pReader);
Testing Writers
• By always writing to a Writer field (as
opposed to hard-wired System.out, etc.),
you can test your classes more easily
• Pass in PipedWriters in your test cases and
check what’s sent to a corresponding
PipedReader
Stream Tokenization
• Often we want to view elements of a stream
as structures larger than the elements
themselves
Stream Tokenization
• Consider the syntactic components of a Java
program: keywords, vars, etc.
class C extends D implements E {…}
• These elements are more complex than just
characters
Stream Tokenization
In such cases, we can place a Façade stream
over the original s.t. the elements of the
Façade are sequences of the original
elements
Stream Tokenizer
• Java provides a built-in StreamTokenizer class
• Warning: The design of this class is ugly
• Always put an Adapter class over it first (or write
your own!)
• This class is very powerful, but it’s biased toward
parsing Java code
Using StreamTokenizer
> Reader r = new BufferedReader(new InputStreamReader(si));
> StreamTokenizer tokenizer = new StreamTokenizer(r);
> tokenizer.nextToken()
42
Download