Download Note

Document related concepts
no text concepts found
Transcript
Lecture 6
Java I/O
Exceptions
Basic Swing
Java I/O classes
Flexible and somewhat slick, but a bit
of a mess
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
InputStream/OutputStream
 Start by studying the java.io.InputStream and
java.io.OutputStream API
 These are base class for performing all binary 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
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
Example with FileInputStream
/* class example DataInput1.java */
/* assumes each char is one byte -- dangerous
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);
}
}
}
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]);
}
}
Higher-level functionality
 FileInputStream and FileOuputStream 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)
Decorator Pattern
 These capabilities are added using a design
called the Decorator Pattern.
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.
Java i/o decorators
 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.
More on 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.
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
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();}}
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;
/* need an exception to know when end of file is hit */
try{
while (true){
data = din.readDouble();
System.out.println(data);
}
}
catch (EOFException eofe){}
BufferedInputStream/BufferedOu
tputStream
 Another common set of decorator classes is
BufferedInputStream and
BufferedOutputStream.
 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 ...
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();}}
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();}}
Other output streams
 FileOutputStream is probably the most common.
 However, note that we could replace
FileOutputStream with other Outputstream in
these examples.
 In this case, the same decorated or undecorated
data will be sent to some other device.
 Good example of this is thread communicatoin,
memory i/o, and socket i/o (using Socket class).
Character-based i/o
Reader and Writer classes
Reader/Writer
 Java maintains a second class hierarchy for
performing higher-level character-based i/o.
 The two base classes in this case are
– java.io.Reader
– java.io.Writer
 Study the API for these classes.
 Very similar to InputStream/OutputStream
 Here I’ll show how to do some common i/o
tasks as examples
Atypical FileWriter Example
/* 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();
}
}
Reading lines from stdin
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);
}}}
Reading by line from file
import java.io.BufferedReader; /*Reader2.java */
import java.io.InputStreamReader;
import java.io.FileInputStream;
public class Reader2{
public static void main(String[] args) throws Exception{
/* convert a FileInputStream, which is an InputStream,
to a Reader by wrapping in InputStreamReader,
then wrap everything in BufferedReader and call
the readLine method to get a line at a time
*/
String input;
String file = args[0];
BufferedReader bin = new BufferedReader
(new InputStreamReader
(new FileInputStream(file)));
while ( (input = bin.readLine()) != null){
System.out.println(input);
} }}
Exercise
 Study the jdk API for GZIPOutputStream
and GZIPInputStream. Write a program that
reads and writes gzip files.
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.
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.
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();
}}}
Related Topics
 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.
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.
Java Exceptions
Intro to Exceptions
 What are exceptions?
– Events that occur during the execution of a
program that interrupt the normal flow of
control.
 One technique for handling Exceptions is to
use return statements in method calls.
 This is fine, but java provides a much more
general and flexible formalism that forces
programmers to consider exceptional cases.
Exception Class hierarchy
Object
• must handle
• may handle
• too serious to catch
Throwable
Error
Exception
many
RuntimeException
IndexOutOfBounds
NullPointerException
Exception Handling Basics
 Three parts to Exception handling
1. claiming exception
2. throwing exception
3. catching exception
 A method has the option of throwing one or more
exceptions when specified conditions occur. This
exception must be claimed by the method. Another
method calling this method must either catch or
rethrow the exception. (unless it is a
RuntimeException)
Claiming Exceptions
 Method declaration must specify every
exception that the method potentially
throws
MethodDeclaration throws Exception1, Exception2, ..., ExceptionN
 Exceptions themselves are concrete
subclasses of Throwable and must be
defined and locatable in regular way.
Throwing Exception
 To throw an Exception, use the throw keyword
followed by an instance of the Exception class
void foo() throws SomeException{
if (whatever) {...}
else{ throw new SomeException(...)}
 We’ll talk about passing data via the Exception
constructor soon.
 Note that if a method foo has a throw clause
within it, that the Exception that is thrown (or one
of its superclasses) must be claimed after the
signature.
Catching Exceptions
 The third piece of the picture is catching
exceptions.
 This is what you will do with most commonly,
since many of java’s library methods are defined
to throw one or more runtime exception.
 Catching exceptions:
– When a method is called that throws and Exception e.g
SomeException, it must be called in a try-catch block:
try{
foo();
}
catch(SomeException se){...}
Catching Exceptions, cont.
 Note that if a method throws an Exception
that is NOT a RuntimeException, you must
do one of two things:
– try-catch it (often called handling it)
– rethrow it
 In the latter case, responsibility then moves
up the calling chain to handle it, and so on
all the way up to main.
More on try-catch
The general form of the try-catch structure is:
try{
/* any number of lines of code
that call any number of methods
with any thrown Exceptions */
}
catch(Exception1 e1){
/* do anything you want here
e.g. change value and try again.
print error and quit
print stacktrace
*/
catch (Exception2 e2){
/* any number of exceptions can be handled ... */
}
Example1
import java.io.*;
public class Exception1{
public static void main(String[] args){
InputStream f;
try{
f = new FileInputStream("foo.txt");
}
catch(FileNotFoundException fnfe){
System.out.println(fnfe.getMessage());
}
}
}
Example2
import java.io.*;
public class Exception2{
public static void main(String[] args){
InputStream fin;
try{
fin = new FileInputStream("foo.txt");
int input = fin.read();
}
catch(FileNotFoundException fnfe){
System.out.println(fnfe.getMessage());
}
catch(IOException ioe){
System.out.println(ioe.getMessage());
} }}
import java.io.*;
public class Exception2{
public static void main(String[] args){
InputStream fin;
try{
fin = new FileInputStream("foo.txt");
int input = fin.read();
}
catch(FileNotFoundException fnfe){
System.out.println(fnfe.getMessage());
}
catch(IOException ioe){
System.out.println(ioe.getMessage());
}
}
}
Recommendations
 Do not use Exceptions to handle normal
conditions in the program that can be
checked with if statements. For example:
– to find the end of an array
– to check if an object is null
 See other commented examples in course
notes.
Creating your own Exceptions
 You can follow this procedure exactly when
creating your own Exception.
 Create a class that subclasses Exception (or
RuntimeException).
 You may also add functionality so that a
relevant message is stored when the error is
thrown, and any other customized
functionality you choose.
 See Exception5.java example
Overview of Swing
Widgets, layouts, events
Miscellaneous tidbits
Creating user interfaces in Java
 Three steps for simple GUI
– Determine what components that you would
like your “form” to contain. Examples are
buttons, checkboxes, text areas, graphics
panels, etc.
– Determine how you would like these panels to
layout on your form. This is the domain of
layout managers.
– Write the event handlers for the GUI.
Creating a GUI application
 Must create a JFrame and call the show()
method. This is normally done by creating a
class that extends JFrame as:
class MyFrame extends JFrame{
MyFrame(){
setSize(300,300); //sets the pixel size
}
main(){
MyFrame frame = new MyFrame();
frame.show();
}
}
Swing Components
Swing components, cont.
 Each component is a Java class with a fairly
extensive inheritency hierarchy:
Object
Component
Container
JComponent
Window
JPanel
Frame
JFrame
Using Swing Components
 Very simple, just create object from
appropriate class – examples:
–
–
–
–
JButton but = new JButton();
JTextField text = new JTextField();
JTextArea text = new JTextArea();
JLabel lab = new JLabel();
 Many more classes. Don’t need to know
every one to get started.
 See ch. 9 Hortsmann
Adding components
 Once a component is created, it can be
added to a container by calling the
container’s add method:
Container cp = getContentPane();
cp.add(new JButton(“cancel”));
cp.add(new JButton(“go”));
How these are laid out is determined by the layout
manager.
Laying out components
 Not so difficult but takes a little practice
 Do not use absolute positioning – not very
portable, does not resize well, etc.
 Use layout managers – basically tells form how to
align components when they’re added.
 Each Container has a layout manager associated
with it.
 A JPanel is a Container – to have different layout
managers associated with different parts of a form,
tile with JPanels and set the desired layout
manager for each JPanel, then add components
directly to panels.
Layout Managers
 Java comes with 7 or 8. Most common and
easiest to use are
– FlowLayout
– BorderLayout
– GridLayout
 Using just these three it is possible to attain
fairly precise layout for most simple
applications.
Setting layout managers
 Very easy to associate a layout manager
with a component. Simply call the
setLayout method on the Container:
JPanel p1 = new JPanel();
p1.setLayout(new FlowLayout(FlowLayout.LEFT));
JPanel p2 = new JPanel();
p2.setLayout(new BorderLayout());
As Components are added to the container, the layout
manager determines their size and positioning.
Event handling
What are events?
 All components can listen for one or more events.
 Typical examples are:
– Mouse movements
– Mouse clicks
– Hitting any key
– Hitting return key
– etc.
 Telling the GUI what to do when a particular
event occurs is the role of the event handler.
ActionEvent
 In Java, most components have a special
event called an ActionEvent.
 This is loosely speaking the most common
or canonical event for that component.
 A good example is a click for a button.
 To have any component listen for
ActionEvents, you must register the
component with an ActionListener. e.g.
– button.addActionListener(new MyAL());
Delegation, cont.
 This is referred to as the Delegation Model.
 When you register an ActionListener with a
component, you must pass it the class which
will handle the event – that is, do the work
when the event is triggered.
 For an ActionEvent, this class must
implement the ActionListener interface.
 This is simple a way of guaranteeing that
the actionPerformed method is defined.
actionPerformed
 The actionPerformed method has the following
signature:
void actionPerformed(ActionEvent)
 The object of type ActionEvent passed to the event
handler is used to query information about the
event.
 Some common methods are:
– getSource()
• object reference to component generating event
– getActionCommand()
• some text associated with event (text on button, etc).
actionPerformed, cont.
 These methods are particularly useful when
using one eventhandler for multiple
components.
Graphics Programming
Using Graphics object
 Use JPanels
– They have a surface on which you can draw.
– They are containers and thus can hold other
components
 How to draw on a Jpanel
Class MyPanel extends JPanel{
public void paintComponent(Graphics g){
//use Graphics methods to draw
}
}
Drawing on a JPanel
 How does this work?
– Framework calls paintComponent
automatically whenever the application needs
to be redrawn.
– Can force this yourself, but do not call
paintComponent directly.
– Instead, call repaint(), which will cause
paintComponent to be called for all
components.
Graphics object method
 Framework hand over an object that
implements the abstract class Graphics.
 Contains functions for drawing shapes to
panel.
 Simplest Example:
Class HelloWorld extends Jpanel{
public void paintComponent(Graphics g){
g.drawString(“Hello World, 50,50”);
}
}
More Graphics Object Methods
 Many more methods. Consult API as
always.
 Typical examples:
–
–
–
–
–
drawOval
drawCircle
drawImage
drawPolyLine
fillArc
Graphics2D Object
 Much more sophisticated rendering
capabilites.
 To access, use same technique and then
downcast Graphics object to Graphics2D
object (latter is subclass of former).
 See Graphics2D API for additional methods
 See DrawTest.java and
Colors
 Use Color class
– 13 standard colors stored as static variables
• Color.red, Color.blue, Color.yellow, etc.
– To specify rbg value, create Color object:
• new Color(int red, int green, int blue);
 Use setPaint(Color) method of Graphics object to
specify a Color.
 Also setBackground(Color) method
 Useful: brighter() and darker() methods for Color
objects
Filling shapes
 Can fill the interior of any closed shape.
 Use fill() method.
 See FillTest.java
Drawing images
 Very fun
 Supports standard GIF images.
Example
Toolkit tk = getDefaultToolkit();
Image img = tk.getImage(“foo.gif);
drawImage(img, 0, 0, null);
Drawing images
 Very fun
 Supports standard GIF images.
Example
Toolkit tk = getDefaultToolkit();
Image img = tk.getImage(“foo.gif);
drawImage(img, 0, 0, null);
Odds and Ends
Timing, system commands, toString
and .equals
Timing Java code
 Simplest is to use static method in System class
double currentTimeMillis();
Example:
public static void main (String args[]){
double begin = System.CurrentTimeMillis();
doWork();
double end = System.CurrentTimeMillis();
double time = (end – begin)/(1000.*60);
System.out.println(“Total time minutes: “ + time);
}
Spawning an OS process
 Very simple but a little different architecturally
 Every java program keeps a single copy of a class
Runtime which allows the user to interact with
the OS
 This is obtained with a static method call
(“Singleton pattern”) and returns a Process object:
Runtime rt = Runtime.getRuntime();
Process p = rt.exec(“ls *.java”);
InputStream in = p.getInputStream();
//question: how to wrap in a reader??
Overriding equals method
 A method boolean equals(Object) also exists in
the object class.
 This method by default determines whether two
Objects point to the same memory location:
SomeObject o1, o2;
o1 = new SomeObject(); o2 = o1;
if (o1.equals(o2)) // yes, same loc in mem
 This is not very useful in general. Good idea to
override with more useful comparison metric
.equals, cont.
 Very good example is String class.
 .equals is overriden for String class to
actually do a character by character
comparison.
 Thus, two String which occupy different
memory but have the same contents are
considered equal.
 Note that using == always does a memory
comparison! Very import!!