FormatIO

Classes to Support Formatted Input and Output

Ron Poet. (ron@dcs.gla.ac.uk)

These classes are designed to enable formatted items such as numbers and words to be read from various input sources and written to a variety of output destinations from Java programs. The initial driving force behind their creation was support for Java as a language for the initial teaching of programming, but they can be used in any situation where sequential input and output is desirable. One obvious application is in unit testing of the non-visual parts of programs, where sequential test data, provided in a file, is superior to non-sequential test data provided interactively.

The FormatIO package defined two interfaces: FormatInput and FormatOutput, together with seven different concrete objects which support these interfaces: Console, FileIn, FileOut, StandardIn, StandardOut, StringIn and StringOut.

 

Console

This class provides a console window that can be written too and read from using FormatOutput and FormatInput. Here is a screen shot of a Console object:

The four buttons do the following:

Save As: Prompts for a file name, and then writes the characters to that file.

Clear: Clears the console window.

Close: Closes the window. A program can have more than one console window.

Quit: Quits the program.

Tabs

The tab key moves the keyboard focus from the text portion of the console window to the buttons, with each press of the tab key moving on to the next button, and eventually back to the text portion of the console. Typing shift-tab moves the keyboard focus in the opposite direction. If the keyboard focus is with one of the buttons, then the only keystroke that is recognised is the Space key, which pushed the button, all other keystrokes being ignored. The tab mechanism makes it possible to use the console window largely without resorting to the mouse, if desired.

Creating a Console Object

A Console object needs to be given a name and size (number of rows and columns) when it is created. Default values are provided if necessary, leading to four constructors.

Console(String name, int nrows, int ncols)

Console(int nrows, int ncols)

Console(String name)

Console()

Four different colours are used to distinguish the text in the Console window.

Red: Error messages, such as the number format error illustrated.

Blue: Text typed by the user and read by the program.

Black: Text produced (written) by the program.

Green: Prompt illustrating the position where the next user entered character will appear. It indicates that the program is waiting for user input.

Error Handling

Console does not throw any exceptions, to make it easy to use for initial programmers. Any errors encountered generate red error messages in the console window. In the above example, fred is not a valid real number, producing the appropriate error message. The input is consumed in the process, and so the correct value can be entered afterwards without blocking the program.

If a large amount of output is produced without any intervening input, then the Console will stop, producing a message indicating a possible infinite loop. The user then has the option of hitting the Quit button to terminate the program or pressing Enter to resume the output.

 

Here is the program that produced the window above:

/*

* TestConsole.java

* ==============

* Copyright (C) 1999, Ron Poet, Dept. Comp.Sci. Uni Glasgow Scotland

* $Author: ron $

* $Date: 1999/08/31 10:33:12 $

* $Revision: 1.4 $

*/

package TestProg;

import FormatIO.*;

/*========================*/

public class TestConsole

/*========================*/

{

/*---------------------------------------*/

public static void main(String[] arg)

/*---------------------------------------*/

{

Console con = new Console(10, 10);

double d = 0;

int i = 0;

con.writeString("\nType a real: ");

d = con.readDouble();

con.writeString("d=");

con.writeDouble(d);

con.writeString("\nType a real: ");

d = con.readDouble();

con.writeString("d=");

con.writeDouble(d);

con.writeString("\nType an int: ");

i = con.readInt();

con.writeString("i=");

con.writeInt(i);

con.writeString("\nType an int: ");

i = con.readInt();

con.writeString("i=");

con.writeInt(i);

}

}

 

 

FileIn and FileOut

These two classes just provide a formatted interface to input and output files. In each case there are two ways of creating the objects.

Providing a name: The named file is opened.

Not providing a name: A FileDialog is produced, which prompts the user for the file name.

FileIn(String name)

FileIn()

FileOut(String name);

FileOut()

Both file types should be closed when no longer needed.

void close()

It is possible to reset a FileIn object, which essentially closes it and opens it again.

void reset()

Error and Exception Handling

An EofX object is thrown when end of file is encountered. This object must be caught by all code using a FileIn object.

File open errors and formatting errors produce error messages which appear on System.err.

 

Example using FileIn

/*

* TestFileIn.java

* ==============

* Copyright (C) 1999, Ron Poet, Dept. Comp.Sci. Uni Glasgow Scotland

* $Author: ron $

* $Date: 1999/08/19 11:02:21 $

* $Revision: 1.1 $

*/

package TestProg;

import FormatIO.*;

/*================*/

class TestFileIn

/*================*/

{

/*----------------------------------------*/

public static void main(String args[])

/*----------------------------------------*/

{

FileIn in1 = new FileIn("file_in");

read(in1);

in1.close();

FileIn in2 = new FileIn();

read(in2);

in2.close();

System.err.println("--- Finished ---");

}

/*-----------------------------------*/

private static void read(FileIn f)

/*-----------------------------------*/

{

try

{

boolean b = f.readBoolean();

String w = f.readWord();

String l1 = f.readLine();

String l2 = f.readLine();

double d = f.readDouble();

int i = f.readInt();

char c = f.readChar();

System.err.println("\nRead");

System.err.println("Boolean: " + ((b) ? "True" : "False"));

System.err.println("Word is [" + w + "]");

System.err.println("Line 1 is [" + l1+ "]");

System.err.println("Line 2 is [" + l2+ "]");

System.err.println("double is [" + d + "]");

System.err.println("int is [" + i + "]");

System.err.println("char is [" + c + "]");

f.readInt(); // generates end of file

}

catch (EofX x)

{

System.err.println("At End of File");

}

catch (Exception x)

{

System.err.println(x.toString());

}

}

}

StringIn and StringOut

In these cases the input comes from a String object, or is sent to a StringBuffer object.

In each case the appropriate String must be provided as an argument to the constructor.

StringIn(String)

StringOut(StringBuffer)

An EofX object is thrown when the end of the String is encountered with StringIn.

Other error conditions produce error messages, in a similar way to the File classes.

 

StandardIn and StandardOut

In these cases the input comes from the standard input System.in, or is sent to the standard output System.out.

The constructors do not need any arguments.

StandardIn()

StandardOut()

An EofX object is thrown when the end of the System.in is.

Other error conditions produce error messages, in a similar way to the File classes.

 

 

FormatInput

The FormatInput interface supports formatted input and conforms to the DataInput style of naming methods. The following three methods are straightforward in that they skip initial white space (space, tab or newline characters) and then return an object of the appropriate type. readInt and readDouble are terminated by the next non numeric character while readBoolean is terminated by the next white space character.

boolean readBoolean();

double readDouble();

int readInt();

These three methods will throw an EofX exception on an attempt to read past end of file, and a NFX exception for number format exception, for example reading an int when the input is "ron" or reading a boolean when the input is not "true" or "false". The derived classes such as Console or FileIn may choose to catch these exceptions themselves and handle them in their own way.

There are several different ways of reading characters and strings, basically depending on whether we want to skip initial white space or not, or whether a string is terminated by white space or not. The convention is that read means skip initial white space, while get means don’t skip initial white space. Also a Word is terminated by the next white space character and Line is terminated by a newline character. This leads to the following five methods.

char readChar(); // skip initial white space

char getChar(); // do not skip initial white space

String readWord(); // skip initial white space, stop at next white space

String readLine(); // skip initial white space, reads line and newline

String getLine(); // reads initial white space, line and newline

readLine will read past the next newline, but does not return the newline character in the String, while getLine will return the initial white space and the terminating newline character as well. All of these methods throw an EofX exception when appropriate.

Finally, we can ignore the rest of the line, including the newline, with

void skipLine();

which also throws EofX when appropriate.

 

 

FormatOutput

The FormatOutput interface provides methods to format the output of all the usual types. It supports the setting of field width, fill character, justification style and precision for real numbers. The method names conform to both the DataOutput or PrintStream styles. All the PrintStream style methods have an alternative println version that appends a newline to the end of their output.

This means that there are a large number of similar methods, and so I will compress their description by introducing a default parameter notation. The default values in each case are:

Width = 0, which means use as many characters as necessary. If a non-zero value such as 10 is provided then 10 output characters will be used, even for a shorter number such as 42. The extra space is padded with fill characters. If more than 10 characters are required, then just enough characters will be used, so that no output is lost.

Precision = 4. This is only used with double values and is the number of digits after the decimal place.

Fill = ‘ ‘. This is the padding character used when the output value has fewer characters than the field width. A value of ‘0’ can be useful for dates and times.

Justification style = RIGHT for numbers and LEFT for strings. In the numeric case the number appears in the right of the output, with fill characters in the left. Possible user supplied values are Format.RIGHT, Format.LEFT and Format.CENTER.

The default parameter notationis used is illustrated by the following example to print a double:

void print(double,int width=0,int precision=4,int fill=’ ‘,int style=RIGHT);

We provide as many parameters as are necessary, with default values being given to the rest. For example:

con.print(x);

con.print(x, 6);

con.print(x, 6, 2);

con.print(x, 6, 2, ‘0’);

con.print(x, 6, 2, ‘0’, Format.CENTER);

PrintStream Style

void print(boolean,int width=0,int fill=’ ‘,int style=LEFT);

void print(double, int width=0,int precision=4,int fill=’ ‘,int style=RIGHT);

void print(int , int width=0,int fill=’ ‘,int style=RIGHT);

void print(char , int width=0,int fill=’ ‘,int style=LEFT);

void print(String, int width=0,int fill=’ ‘,int style=LEFT);

All of these methods have a println version as well.

DataOutput Style

void writeBoolean(boolean,int width=0,int fill=’ ‘,int style=LEFT);

void writeDouble (double, int width=0,int precision=4,int fill=’ ‘,

int style=RIGHT);

void writeInt (int , int width=0,int fill=’ ‘,int style=RIGHT);

void writeChar (char , int width=0,int fill=’ ‘,int style=LEFT);

void writeString (String, int width=0,int fill=’ ‘,int style=LEFT);