// TextFileInput.java
// Copyright (c) 2000, 2005 Dorothy L. Nixon. All rights reserved.
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
/**
* Simplified buffered character input
* stream from an input text file.
* Manages an input text file,
* handling all IOExceptions by generating
* RuntimeExcpetions (run-time error
* messages).
*
* If the text file cannot be created,
* a RuntimeException is thrown,
* which by default results an an
* error message being printed to
* the standard error stream.
*
* @author D. Nixon
*/
public class TextFileInput {
/** Name of text file */
private String filename;
/** Buffered character stream from file */
private BufferedReader br;
/** Count of lines read so far. */
private int lineCount = 0;
/**
* Creates a buffered character input
* strea, for the specified text file.
*
* @param filename the input text file.
* @exception RuntimeException if an
* IOException is thrown when
* attempting to open the file.
*/
public TextFileInput(String filename)
{
this.filename = filename;
try {
br = new BufferedReader(
new InputStreamReader(
new FileInputStream(filename)));
} catch ( IOException ioe ) {
throw new RuntimeException(ioe);
} // catch
} // constructor
/**
* Closes this character input stream.
* No more characters can be read from
* this TextFileInput once it is closed.
* @exception NullPointerException if
* the file is already closed.
* @exception RuntimeException if an
* IOException is thrown when
* closing the file.
*/
public void close()
{
try {
br.close();
br = null;
} catch ( NullPointerException npe ) {
throw new NullPointerException(
filename + "already closed.");
} catch ( IOException ioe ) {
throw new RuntimeException(ioe);
} // catch
} // method close
/**
* Reads a line of text from the file and
* positions cursor at 0 for the next line.
* Reads from the current cursor position
* to end of line.
* Implementation does not invoke read.
*
* @return the line of text, with
* end-of-line marker deleted.
* @exception RuntimeException if an
* IOException is thrown when
* attempting to read from the file.
*/
public String readLine()
{
return readLineOriginal();
} // method readLine()
/**
* Returns a count of lines
* read from the file so far.
*/
public int getLineCount() { return lineCount; }
/**
* Tests whether the specified character is equal,
* ignoring case, to one of the specified options.
*
* @param toBeChecked the character to be tested.
* @param options a set of characters
* @return true if <code>toBeChecked</code> is
* equal, ignoring case, to one of the
* <code>options</code>, false otherwise.
*/
public static boolean isOneOf(char toBeChecked,
char[] options)
{
boolean oneOf = false;
for ( int i = 0; i < options.length && !oneOf; i++ )
if ( Character.toUpperCase(toBeChecked)
== Character.toUpperCase(options[i]) )
oneOf = true;
return oneOf;
} // method isOneOf(char, char[])
/**
* Tests whether the specified string is one of the
* specified options. Checks whether the string
* contains the same sequence of characters (ignoring
* case) as one of the specified options.
*
* @param toBeChecked the String to be tested
* @param options a set of Strings
* @return true if <code>toBeChecked</code>
* contains the same sequence of
* characters, ignoring case, as one of the
* <code>options</code>, false otherwise.
*/
public static boolean isOneOf(String toBeChecked,
String[] options)
{
boolean oneOf = false;
for ( int i = 0; i < options.length && !oneOf; i++ )
if ( toBeChecked.equalsIgnoreCase(options[i]) )
oneOf = true;
return oneOf;
} // method isOneOf(String, String[])
/**
* Reads a line from the text file and ensures that
* it matches one of a specified set of options.
*
* @param options array of permitted replies
*
* @return the line of text, if it contains the same
* sequence of characters (ignoring case for
* letters) as one of the specified options,
* null otherwise.
* @exception RuntimeException if the line of text
* does not match any of the specified options,
* or if an IOException is thrown when reading
* from the file.
* @exception NullPointerException if no options are
* provided, or if the end of the file has been
* reached.
*/
public String readSelection(String[] options)
{
if ( options == null || options.length == 0 )
throw new NullPointerException(
"No options provided for "
+ " selection to be read in file "
+ filename + ", line "
+ (lineCount + 1) + ".");
String answer = readLine();
if ( answer == null )
throw new NullPointerException(
"End of file "
+ filename + "has been reached.");
if ( !TextFileInput.isOneOf(answer, options) ) {
String optionString = options[0];
for ( int i = 1; i < options.length; i++ )
optionString += ", " + options[i];
throw new RuntimeException("File " + filename
+ ", line " + lineCount
+ ": \"" + answer
+ "\" not one of "
+ optionString + ".");
} // if
return answer;
} // method readSelection
/**
* Reads a line from the text file and ensures that
* it matches, ignoring case, one of "Y", "N", "yes",
* "no", "1", "0", "T", "F", "true", or "false".
* There must be no additional characters on the line.
*
* @return <code>true</code> if the line matches
* "Y", "yes", "1" "T", or "true".
* <code>false</code> if the line matches
* "N", "no", "0", "F", or "false".
* @exception RuntimeException if the line of text
* does not match one of "Y", "N", "yes",
* "no", "1", "0", "T", "F", "true", or "false",
* or if an IOException is thrown when reading
* from the file.
* @exception NullPointerException if the end of the
* file has been reached.
*/
public boolean readBooleanSelection()
{
String[] options = {"Y", "N", "yes", "no", "1", "0",
"T", "F", "true", "false"};
String answer = readSelection(options);
return isOneOf(answer,
new String[] {"Y", "yes", "1", "T", "true"} );
} // method askUserYesNo
/**
* Reads a line of text from the file and
* increments line count. (This method
* is called by public readLine and is
* final to facilitate avoidance of side
* effects when public readLine is overridden.)
*
* @return the line of text, with
* end-of-line marker deleted.
* @exception RuntimeException if an
* IOException is thrown when
* attempting to read from the file.
*/
protected final String readLineOriginal()
{
try {
if ( br == null )
throw new RuntimeException(
"Cannot read from closed file "
+ filename + ".");
String line = br.readLine();
if ( line != null )
lineCount++;
return line;
} catch (IOException ioe) {
throw new RuntimeException(ioe);
} // catch
} // method readLineOriginal
} // class TextFileInput