import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import javax.swing.JOptionPane;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.IllegalFormatException;
import java.util.Random;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
* Simplifies some common tasks, such as I/O, for beginning programmers.
*
*
This is a framework designed to make introductory
* programming in Java a little easier. Additions to
* this framework to make both sequential and random
* access file processing easier are planned for the
* near future.
*
* To use this class, just subclass it by extending it
* and your class will be able to do print, println,
* and printf without specifying System.out. Input from
* the keyboard can be achieved by using the getLine(),
* getLong(), getInt(), etc. methods from this class.
* An optional prompt can be passed to these methods.
*
* Although not good from a software design point of view,
* most exceptions are not passed back to the calling
* methods since the goal of this class is to simplify
* programming for beginners.
*
* This code is covered as GPL V.3 licensed software.
*
* Version information:
*
* 0.1 print,println, and printf methods provided
* getByte(), getLong(), etc provided in both plain
* and with prompt passable
* 0.2 added primitive console clearing with
* clearConsole() method - outputs 50 blank lines to
* scroll most output off screen
* 0.3 added getChar() and getChar(String) methods
* 0.4 added delay(double seconds) for pausing
* added random() to get random integer
* added random(int n) to get random integer 1-n
* added random(int lo, int hi) to get random integer lo-hi
* 0.5 added SequentialFile classes to make file I/O easier
* 0.5.1 bugfix and added feature to make reading of file data
* more lenient
* 0.6 support added for random access files using RandomFile class
* 0.7 added a number of utility routines for string handling and
* simple GUI messaging
* 0.7.1 fixed a bug in the random access routines where filelength
* was erroneously increased on puts which were not at the end
* of the file. Also added lcase$() and ucase$() methods.
* 0.7.2 added select method, optional bounding on keyboard data entry,
* and the new formatCurrency methods
* 0.7.3 added file functions: isWriteable, isReadable, isRegularFile,
* isDirectory, exists, deleteFile, renameFile, copyFile, mkdir, resizeToBytes,
* and resizeToRecords; also added formatCurrencyFixed to always
* return the same size string (unless overflow demands otherwise)
* 0.7.4 added the ability to use primitive data types in arrays for
* random access records
* 0.7.5 made it so random access files can use dirty records with incorrect
* string sizes as the record parameter when opening the file
* 0.7.6 added getChar(String, String) method for prompt and allowed character
* response set; also tweaked some file read/write code
* 0.7.7 added formatted prompt methods: getfByte, getfChar, getfShort,
* getfInt, getfLong, getfFloat, getfDouble, getfBoolean, getfString,
* getfLine; fixed bug in getByte(String, int, int)
* 0.7.8 added enhanced getBoolean and getfBoolean methods that allow
* caller-defined case-insensitive true and false values; also added
* additional GUI input methods: promptBoolean, promptByte, promptChar,
* promptDouble, promptFloat, promptInt, promptShort, promptLong; also
* changed indent levels from 3 to 4 spaces; added promptSelect and
* promptSelectWithHeading methods
* 0.7.9 modified RandomFile get(long) to create new object to return each
* time rather than reusing the same object every time; added ucase$(char),
* ucase(char), lcase$(char), lcase(char); added code to swap min and
* max values if user gets them reversed in the getxxx methods; corrected
* and standardized indentation throughout code
* 0.7.10 added repeat(char ch, int count),
* repeat(String str, int count),
* getString(String prompt, int minLength),
* getString(String prompt, int minLength, int maxLength),
* getString(String prompt, String[] allowed),
* getString(String prompt, String[] allowed, boolean caseSensitive),
* getString(String prompt, String regex),
* getString(String prompt, String regex, boolean caseSensitive),
* getLine(String prompt, int minLength),
* getLine(String prompt, int minLength, int maxLength),
* getLine(String prompt, String[] allowed),
* getLine(String prompt, String[] allowed, boolean caseSensitive),
* getLine(String prompt, String regex),
* getLine(String prompt, String regex, boolean caseSensitive),
* 0.7.11 added getHex(),
* getHex(long lo, long hi)
* getHex(String prompt)
* getHex(String prompt, long lo, long hi)
* getOctal(),
* getOctal(long lo, long hi)
* getOctal(String prompt)
* getOctal(String prompt, long lo, long hi)
* getBinary(),
* getBinary(long lo, long hi)
* getBinary(String prompt)
* getBinary(String prompt, long lo, long hi)
*
*Issues:
*
*- Clearing the console window in Windows from Java is
* non-obvious. Solutions include:
*
* - installing an ANSI driver and sending escape sequences,
* but this requires setting up the ANSI driver in
* config.sys and makes this code platform-specific
* - creating a DLL which can be called using JNI, which is
* slick, but I'm worried about DLL compatability problems
* with different versions of Windows and that this
* solution makes this code platform-specific
* - just ouputting a bunch of blank lines and hoping that
* all the text in the console window is scrolled off; this
* is what is implemented here using 50 lines as a likely
* maximum line count the user would have the window open to
* - creating a GUI version of the console window; this would
* be the best alternative, allowing numerous custom
* enhancements including keystroke and mouse event capturing;
* this will probably be the future direction of this codebase
* - especially since it is a cross-platform solution
*
*
* Note: The name clearConsole() was chosen for the implemented
* solution so the names cls() and clear() would be available
* for a more elegant solution later
*
* @author David G. Klick
* @version 0.7.11, 2015-09-07
*
*/
public class CIS111App {
/**
* Defines allowed modes for opening sequential access files.
*
* @author David G. Klick
* @version 0.7.11, 2015-09-07
*/
protected enum FileMode {
/**
* Tells program to read from file starting at the beginning of the file.
*/
INPUT,
/**
* Tells program to write to the file starting at the beginning of the file.
* This erases any previous data in the file.
*/
OUTPUT,
/**
* Tells program to write to the file starting at the end of the file.
* This preserves any previous data in the file.
*/
APPEND }
protected static final String VERSION = "0.7.10";
private static Random rnd = new Random();
private static Scanner in = new Scanner(System.in);
/**
* Clears the console in a primitive way by writing 50 blank
* lines to stdout.
*/
public static void clearConsole() {
String newlines = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
print(newlines + newlines);
}
/**
* Causes a delay for a specific number of seconds.
*
* @param seconds The number of seconds of delay requested. This number
* is a double so the calling application can request
* delays of a fraction of a second. For instance .1 would
* request a 1/10 of a second delay. Delays are not precise,
* but are "accurate enough" on the 1/10 of a second and
* greater time scale.
*/
public static void delay(double seconds) {
try {
Thread.sleep((long)(seconds*1000));
} catch (InterruptedException e) {
// do nothing
}
}
/**
* Obtains a string representation of a Boolean value from stdin and
* returns it as a boolean value.
*
* @return A boolean version of a Boolean value typed into stdin.
*/
public static boolean getBoolean() {
return Boolean.parseBoolean(in.nextLine());
}
/**
* Displays a prompt and obtains a string representation
* of a Boolean value from stdin and
* returns it as a boolean value.
*
* @param prompt The prompt displayed to the user.
*
* @return A boolean version of a Boolean value typed into stdin.
*/
public static boolean getBoolean(String prompt) {
print(prompt);
return getBoolean();
}
/**
* Displays a prompt and obtains a string representation
* of a Boolean value from stdin. This method uses a caller-
* supplied list of possible true and false values and
* returns it as a boolean value. The user supplied values
* are used case-insensitively.
*
* @param prompt The prompt displayed to the user.
*
* @param strTrue A comma-separated list of allowed true values.
*
* @param strFalse A comma-separated list of allowed false values.
*
* @return A boolean version of a Boolean value typed into stdin.
*/
public static boolean getBoolean(String prompt, String strTrue, String strFalse) {
HashMap map = new HashMap();
StringTokenizer tok = new StringTokenizer(strTrue, ",");
while (tok.hasMoreTokens()) map.put(tok.nextToken().toUpperCase(), Boolean.TRUE);
tok = new StringTokenizer(strFalse, ",");
while (tok.hasMoreTokens()) map.put(tok.nextToken().toUpperCase(), Boolean.FALSE);
String s = null;
boolean valid = false;
print(prompt);
while (!valid) {
s = in.nextLine().toUpperCase();
if (!map.containsKey(s)) {
print("Invalid entry, please re-enter: ");
} else {
valid = true;
}
}
return map.get(s).booleanValue();
}
/**
* Displays a formatted prompt and obtains a string representation
* of a Boolean value from stdin and returns it as a boolean value.
* Uses the System.out.printf formatting rules.
*
* @param format A format string as described in the Format string syntax
* section of the Java API documentation
* @param args Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers,
* the extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined
* by the Java Virtual Machine Specification. The behaviour on
* a null argument depends on the conversion.
* @exception IllegalFormatException If a format string contains an illegal
* syntax, a format specifier that is incompatible with the
* given arguments, insufficient arguments given the format
* string, or other illegal conditions. For specification of
* all possible formatting errors, see the Details section of
* the formatter class specification.
* @exception NullPointerException If the format is null
*
* @return A boolean version of a Boolean value typed into stdin.
*/
public static boolean getfBoolean(String format, Object... args) {
printf(format, args);
return getBoolean();
}
/**
* Obtains a byte value from stdin within a range specified by the arguments.
*
* @param lo The lowest byte value accepted.
*
* @param hi The highest byte value accepted.
*
* @return The byte value typed in.
*/
public static byte getByte(byte lo, byte hi) {
boolean valid = false;
byte num = 0;
// swap hi and lo if they are reversed
if (hi < lo) {
byte temp = hi;
hi = lo;
lo = temp;
}
while (!valid) {
try {
String s = in.nextLine();
num = Byte.parseByte(s);
if (num < lo || num > hi) {
print("Byte value must be between " + lo + " and " + hi
+ ", please re-enter: ");
} else {
valid = true;
}
} catch (NumberFormatException e) {
print("Invalid byte value, please re-enter: ");
}
}
return num;
}
/**
* Obtains a byte value from stdin.
*
* @return The byte value typed in.
*/
public static byte getByte() {
return getByte(Byte.MIN_VALUE, Byte.MAX_VALUE);
}
/**
* Displays a prompt and obtains a byte value from stdin.
*
* @param prompt The prompt displayed to the user.
*
* @return The byte value typed in.
*/
public static byte getByte(String prompt) {
print(prompt);
return getByte();
}
/**
* Displays a prompt and obtains a byte value from stdin
* within the range specified by the arguments.
*
* @param prompt The prompt displayed to the user.
*
* @param lo The lowest byte value accepted.
*
* @param hi The highest byte value accepted.
*
* @return The byte value typed in.
*/
public static byte getByte(String prompt, byte lo, byte hi) {
print(prompt);
return getByte(lo, hi);
}
/**
* Displays a formatted prompt and obtains a byte value from stdin.
*
* @param format A format string as described in the Format string syntax
* section of the Java API documentation.
* @param args Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers,
* the extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined
* by the Java Virtual Machine Specification. The behaviour on
* a null argument depends on the conversion.
* If there are two more arguments following the format string
* than there are conversion specifiers in the format string,
* then the last two arguments will be used as the minimum
* and maximum allowed values.
*
* @exception IllegalFormatException If a format string contains an illegal
* syntax, a format specifier that is incompatible with the
* given arguments, insufficient arguments given the format
* string, or other illegal conditions. For specification of
* all possible formatting errors, see the Details section of
* the formatter class specification.
* @exception NullPointerException If the format is null
* @exception IllegalArgumentException If the number of arguments does not match
* either the number required by the format string or an optional two
* additional arguments for low and high values
*
* @return A byte value typed into stdin.
*/
public static byte getfByte(String format, Object... args) {
byte b = 0;
int n = conversionSpecifiers(format);
if (n == args.length) {
b = getByte(String.format(format, args));
} else if (n == args.length-2) {
byte lo = Byte.MIN_VALUE, hi = Byte.MAX_VALUE;
try {
lo = Byte.parseByte(args[args.length-2].toString());
hi = Byte.parseByte(args[args.length-1].toString());
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
Object[] newargs = new Object[args.length-2];
for (int i=0; i hi) {
print("Double value must be between " + lo + " and " + hi
+ ", please re-enter: ");
} else {
valid = true;
}
} catch (NumberFormatException e) {
print("Invalid double value, please re-enter: ");
}
}
return num;
}
/**
* Displays a prompt and obtains a double value from stdin.
*
* @param prompt The prompt displayed to the user.
*
* @return The double value typed into stdin.
*/
public static double getDouble(String prompt) {
print(prompt);
return getDouble();
}
/**
* Displays a prompt and obtains a double value from stdin
* within a range specified by the arguments.
*
* @param prompt The prompt displayed to the user.
*
* @param lo The lowest double value accepted.
*
* @param hi The highest double value accepted.
*
* @return The double value typed into stdin.
*/
public static double getDouble(String prompt, double lo, double hi) {
print(prompt);
return getDouble(lo, hi);
}
/**
* Displays a formatted prompt and obtains a double value from stdin.
*
* @param format A format string as described in the Format string syntax
* section of the Java API documentation
* @param args Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers,
* the extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined
* by the Java Virtual Machine Specification. The behaviour on
* a null argument depends on the conversion.
* If there are two more arguments following the format string
* than there are conversion specifiers in the format string,
* then the last two arguments will be used as the minimum
* and maximum allowed values.
* @exception IllegalFormatException If a format string contains an illegal
* syntax, a format specifier that is incompatible with the
* given arguments, insufficient arguments given the format
* string, or other illegal conditions. For specification of
* all possible formatting errors, see the Details section of
* the formatter class specification.
* @exception NullPointerException If the format is null
* @exception IllegalArgumentException If the number of arguments does not match
* either the number required by the format string or an optional two
* additional arguments for low and high values
*
* @return The double value typed into stdin.
*/
public static double getfDouble(String format, Object... args) {
double d = 0.0;
int n = conversionSpecifiers(format);
if (n == args.length) {
d = getDouble(String.format(format, args));
} else if (n == args.length-2) {
double lo = -Double.MAX_VALUE, hi = Double.MAX_VALUE;
try {
lo = Double.parseDouble(args[args.length-2].toString());
hi = Double.parseDouble(args[args.length-1].toString());
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
Object[] newargs = new Object[args.length-2];
for (int i=0; i hi) {
print("Float value must be between " + lo + " and " + hi
+ ", please re-enter: ");
} else {
valid = true;
}
} catch (NumberFormatException e) {
print("Invalid float value, please re-enter: ");
}
}
return num;
}
/**
* Displays a prompt and obtains a float value from stdin.
*
* @param prompt The prompt displayed to the user.
*
* @return The float value typed into stdin.
*/
public static float getFloat(String prompt) {
print(prompt);
return getFloat();
}
/**
* Displays a prompt and obtains a float value from stdin
* within a range specified by the arguments.
*
* @param prompt The prompt displayed to the user.
*
* @param lo The lowest float value accepted.
*
* @param hi The highest float value accepted.
*
* @return The float value typed into stdin.
*/
public static float getFloat(String prompt, float lo, float hi) {
print(prompt);
return getFloat(lo, hi);
}
/**
* Displays a formatted prompt and obtains a float value from stdin.
*
* @param format A format string as described in the Format string syntax
* section of the Java API documentation
* @param args Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers,
* the extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined
* by the Java Virtual Machine Specification. The behaviour on
* a null argument depends on the conversion.
* If there are two more arguments following the format string
* than there are conversion specifiers in the format string,
* then the last two arguments will be used as the minimum
* and maximum allowed values.
* @exception IllegalFormatException If a format string contains an illegal
* syntax, a format specifier that is incompatible with the
* given arguments, insufficient arguments given the format
* string, or other illegal conditions. For specification of
* all possible formatting errors, see the Details section of
* the formatter class specification.
* @exception NullPointerException If the format is null
* @exception IllegalArgumentException If the number of arguments does not match
* either the number required by the format string or an optional two
* additional arguments for low and high values
*
* @return The float value typed into stdin.
*/
public static float getfFloat(String format, Object... args) {
float f = 0.0f;
int n = conversionSpecifiers(format);
if (n == args.length) {
f = getFloat(String.format(format, args));
} else if (n == args.length-2) {
float lo = -Float.MAX_VALUE, hi = Float.MAX_VALUE;
try {
lo = Float.parseFloat(args[args.length-2].toString());
hi = Float.parseFloat(args[args.length-1].toString());
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
Object[] newargs = new Object[args.length-2];
for (int i=0; i hi) {
print("Integer value must be between " + lo + " and " + hi
+ ", please re-enter: ");
} else {
valid = true;
}
} catch (NumberFormatException e) {
print("Invalid integer, please re-enter: ");
}
}
return num;
}
/**
* Displays a prompt and obtains an int value from stdin.
*
* @param prompt The prompt displayed to the user.
*
* @return The int value typed into stdin.
*/
public static int getInt(String prompt) {
print(prompt);
return getInt();
}
/**
* Displays a prompt and obtains an int value from stdin
* within a range specified by the arguments.
*
* @param prompt The prompt displayed to the user.
*
* @param lo The lowest int value accepted.
*
* @param hi The highest int value accepted.
*
* @return The int value typed into stdin.
*/
public static int getInt(String prompt, int lo, int hi) {
print(prompt);
return getInt(lo, hi);
}
/**
* Displays a formatted prompt and obtains an int value from stdin.
*
* @param format A format string as described in the Format string syntax
* section of the Java API documentation
* @param args Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers,
* the extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined
* by the Java Virtual Machine Specification. The behaviour on
* a null argument depends on the conversion.
* If there are two more arguments following the format string
* than there are conversion specifiers in the format string,
* then the last two arguments will be used as the minimum
* and maximum allowed values.
* @exception IllegalFormatException If a format string contains an illegal
* syntax, a format specifier that is incompatible with the
* given arguments, insufficient arguments given the format
* string, or other illegal conditions. For specification of
* all possible formatting errors, see the Details section of
* the formatter class specification.
* @exception NullPointerException If the format is null
* @exception IllegalArgumentException If the number of arguments does not match
* either the number required by the format string or an optional two
* additional arguments for low and high values
*
* @return An int value typed into stdin.
*/
public static int getfInt(String format, Object... args) {
int num = 0;
int n = conversionSpecifiers(format);
if (n == args.length) {
num = getInt(String.format(format, args));
} else if (n == args.length-2) {
int lo = Integer.MIN_VALUE, hi = Integer.MAX_VALUE;
try {
lo = Integer.parseInt(args[args.length-2].toString());
hi = Integer.parseInt(args[args.length-1].toString());
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
Object[] newargs = new Object[args.length-2];
for (int i=0; i maxLength) {
printf("Error: Input greater than maximum length (%d)\n", maxLength);
} else {
valid = true;
}
}
return str;
}
/**
* Displays a prompt and obtains a line of input (up to a newline) from stdin.
* Requires that the input string is among the elements in the allowed aray.
*
* @param prompt A prompt to be displayed to the user.
* @param allowed An array of String objects. The user input must
* match one of these Strings (case sensitive).
*
* @return A line of text from stdin as a String. This is generally what
* the user has typed in on the keyboard.
*/
public static String getLine(String prompt, String[] allowed) {
return getLine(prompt, allowed, true);
}
/**
* Displays a prompt and obtains a line of input (up to a newline) from stdin.
* Requires that the input string is among the elements in the allowed aray.
*
* @param prompt A prompt to be displayed to the user.
* @param allowed An array of String objects. The user input must
* match one of these Strings.
* @param caseSensitive Specifies whether the user input match to what
* is allowed will be case sensitive.
*
* @return A line of text from stdin as a String. This is generally what
* the user has typed in on the keyboard.
*/
public static String getLine(String prompt, String[] allowed, boolean caseSensitive) {
String str = null;
boolean valid = false;
while (!valid) {
str = getLine(prompt);
for (int i=0; i hi) {
print("Long integer value must be between " + lo + " and " + hi
+ ", please re-enter: ");
} else {
valid = true;
}
} catch (NumberFormatException e) {
print("Invalid long value, please re-enter: ");
}
}
return num;
}
/**
* Obtains a long int hex value from stdin.
*
* @return The long int hex value typed in.
*/
public static long getHex() {
return getHex(Long.MIN_VALUE, Long.MAX_VALUE);
}
/**
* Displays a prompt and obtains a hex value from stdin.
*
* @param prompt The prompt displayed to the user.
*
* @return The hex value typed in.
*/
public static long getHex(String prompt) {
print(prompt);
return getHex();
}
/**
* Displays a prompt and obtains a hex value from stdin
* within the range specified by the arguments.
*
* @param prompt The prompt displayed to the user.
*
* @param lo The lowest hex value accepted.
*
* @param hi The highest hex value accepted.
*
* @return The byte value typed in.
*/
public static long getHex(String prompt, long lo, long hi) {
print(prompt);
return getHex(lo, hi);
}
/**
* Obtains a long int value in hexadecimal form from stdin
* within a range specified by the arguments.
*
* @param lo The lowest long int value accepted.
*
* @param hi The highest long int value accepted.
*
* @return The long int value typed into stdin.
*/
public static long getHex(long lo, long hi) {
boolean valid = false;
long num = 0;
// swap hi and lo if they are reversed
if (hi < lo) {
long temp = hi;
hi = lo;
lo = temp;
}
while (!valid) {
try {
String s = in.nextLine();
num = Long.parseLong(s, 16);
if (num < lo || num > hi) {
printf("Hex value must be between %s and %s, please re-enter: ",
Long.toHexString(lo), Long.toHexString(hi));
} else {
valid = true;
}
} catch (NumberFormatException e) {
print("Invalid hex value, please re-enter: ");
}
}
return num;
}
/**
* Obtains a long int octal value from stdin.
*
* @return The long int octal value typed in.
*/
public static long getOctal() {
return getOctal(Long.MIN_VALUE, Long.MAX_VALUE);
}
/**
* Displays a prompt and obtains an octal value from stdin.
*
* @param prompt The prompt displayed to the user.
*
* @return The octal value typed in.
*/
public static long getOctal(String prompt) {
print(prompt);
return getOctal();
}
/**
* Displays a prompt and obtains an octal value from stdin
* within the range specified by the arguments.
*
* @param prompt The prompt displayed to the user.
*
* @param lo The lowest octal value accepted.
*
* @param hi The highest octal value accepted.
*
* @return The octal value typed in.
*/
public static long getOctal(String prompt, long lo, long hi) {
print(prompt);
return getOctal(lo, hi);
}
/**
* Obtains a long int value in octal form from stdin
* within a range specified by the arguments.
*
* @param lo The lowest long int value accepted.
*
* @param hi The highest long int value accepted.
*
* @return The long int value typed into stdin.
*/
public static long getOctal(long lo, long hi) {
boolean valid = false;
long num = 0;
// swap hi and lo if they are reversed
if (hi < lo) {
long temp = hi;
hi = lo;
lo = temp;
}
while (!valid) {
try {
String s = in.nextLine();
num = Long.parseLong(s, 8);
if (num < lo || num > hi) {
printf("Octal value must be between %s and %s, please re-enter: ",
Long.toOctalString(lo), Long.toOctalString(hi));
} else {
valid = true;
}
} catch (NumberFormatException e) {
print("Invalid octal value, please re-enter: ");
}
}
return num;
}
/**
* Obtains a long int binary value from stdin.
*
* @return The long int binary value typed in.
*/
public static long getBinary() {
return getBinary(Long.MIN_VALUE, Long.MAX_VALUE);
}
/**
* Displays a prompt and obtains a binary value from stdin.
*
* @param prompt The prompt displayed to the user.
*
* @return The binary value typed in.
*/
public static long getBinary(String prompt) {
print(prompt);
return getBinary();
}
/**
* Displays a prompt and obtains a binary value from stdin
* within the range specified by the arguments.
*
* @param prompt The prompt displayed to the user.
*
* @param lo The lowest binary value accepted.
*
* @param hi The highest binary value accepted.
*
* @return The byte value typed in.
*/
public static long getBinary(String prompt, long lo, long hi) {
print(prompt);
return getBinary(lo, hi);
}
/**
* Obtains a long int value in binary form from stdin
* within a range specified by the arguments.
*
* @param lo The lowest long int value accepted.
*
* @param hi The highest long int value accepted.
*
* @return The long int value typed into stdin.
*/
public static long getBinary(long lo, long hi) {
boolean valid = false;
long num = 0;
// swap hi and lo if they are reversed
if (hi < lo) {
long temp = hi;
hi = lo;
lo = temp;
}
while (!valid) {
try {
String s = in.nextLine();
num = Long.parseLong(s, 2);
if (num < lo || num > hi) {
printf("Binary value must be between %s and %s, please re-enter: ",
Long.toBinaryString(lo), Long.toBinaryString(hi));
} else {
valid = true;
}
} catch (NumberFormatException e) {
print("Invalid binary value, please re-enter: ");
}
}
return num;
}
/**
* Displays a prompt and obtains a long int value from stdin.
*
* @param prompt The prompt displayed to the user.
*
* @return The long int value typed into stdin.
*/
public static long getLong(String prompt) {
print(prompt);
return getLong();
}
/**
* Displays a prompt and obtains a long int value from stdin
* within a range specified by the arguments.
*
* @param prompt The prompt displayed to the user.
*
* @param lo The lowest long int value accepted.
*
* @param hi The highest long int value accepted.
*
* @return The long int value typed into stdin.
*/
public static long getLong(String prompt, long lo, long hi) {
print(prompt);
return getLong(lo, hi);
}
/**
* Displays a formatted prompt and obtains a long value from stdin.
*
* @param format A format string as described in the Format string syntax
* section of the Java API documentation
* @param args Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers,
* the extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined
* by the Java Virtual Machine Specification. The behaviour on
* a null argument depends on the conversion.
* If there are two more arguments following the format string
* than there are conversion specifiers in the format string,
* then the last two arguments will be used as the minimum
* and maximum allowed values.
* @exception IllegalFormatException If a format string contains an illegal
* syntax, a format specifier that is incompatible with the
* given arguments, insufficient arguments given the format
* string, or other illegal conditions. For specification of
* all possible formatting errors, see the Details section of
* the formatter class specification.
* @exception NullPointerException If the format is null
* @exception IllegalArgumentException If the number of arguments does not match
* either the number required by the format string or an optional two
* additional arguments for low and high values
*
* @return A long value typed into stdin.
*/
public static long getfLong(String format, Object... args) {
long num = 0;
int n = conversionSpecifiers(format);
if (n == args.length) {
num = getLong(String.format(format, args));
} else if (n == args.length-2) {
long lo = Long.MIN_VALUE, hi = Long.MAX_VALUE;
try {
lo = Long.parseLong(args[args.length-2].toString());
hi = Long.parseLong(args[args.length-1].toString());
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
Object[] newargs = new Object[args.length-2];
for (int i=0; i hi) {
print("Short integer value must be between " + lo + " and " + hi
+ ", please re-enter: ");
} else {
valid = true;
}
} catch (NumberFormatException e) {
print("Invalid short value, please re-enter: ");
}
}
return num;
}
/**
* Displays a prompt and obtains a short int value from stdin
*
* @param prompt The prompt displayed to the user.
*
* @return The short int value typed into stdin.
*/
public static short getShort(String prompt) {
print(prompt);
return getShort();
}
/**
* Displays a prompt and obtains a short int value from stdin
* within a range specified by the arguments.
*
* @param prompt The prompt displayed to the user.
*
* @param lo The lowest short int value accepted.
*
* @param hi The highest short int value accepted.
*
* @return The short int value typed into stdin.
*/
public static short getShort(String prompt, short lo, short hi) {
print(prompt);
return getShort(lo, hi);
}
/**
* Displays a formatted prompt and obtains a short value from stdin.
*
* @param format A format string as described in the Format string syntax
* section of the Java API documentation
* @param args Arguments referenced by the format specifiers in the format
* string. If there are more arguments than format specifiers,
* the extra arguments are ignored. The number of arguments is
* variable and may be zero. The maximum number of arguments is
* limited by the maximum dimension of a Java array as defined
* by the Java Virtual Machine Specification. The behaviour on
* a null argument depends on the conversion.
* If there are two more arguments following the format string
* than there are conversion specifiers in the format string,
* then the last two arguments will be used as the minimum
* and maximum allowed values.
* @exception IllegalFormatException If a format string contains an illegal
* syntax, a format specifier that is incompatible with the
* given arguments, insufficient arguments given the format
* string, or other illegal conditions. For specification of
* all possible formatting errors, see the Details section of
* the formatter class specification.
* @exception NullPointerException If the format is null
* @exception IllegalArgumentException If the number of arguments does not match
* either the number required by the format string or an optional two
* additional arguments for low and high values
*
* @return A short value typed into stdin.
*/
public static short getfShort(String format, Object... args) {
short num = 0;
int n = conversionSpecifiers(format);
if (n == args.length) {
num = getShort(String.format(format, args));
} else if (n == args.length-2) {
short lo = Short.MIN_VALUE, hi = Short.MAX_VALUE;
try {
lo = Short.parseShort(args[args.length-2].toString());
hi = Short.parseShort(args[args.length-1].toString());
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
Object[] newargs = new Object[args.length-2];
for (int i=0; ilimit.
*/
public static int random(int limit) {
return rnd.nextInt(limit) + 1;
}
/**
* Returns a random integer in a range. The range is determined by
* the value of the lo and hi paramters.
*
* @param lo Determines the low end of the range of the random number
* returned.
*
* @param hi Determines the high end of the range of the random number
* returned.
*
* @return A random number in the range lo through hi inclusive.
*/
public static int random(int lo, int hi) {
if (lo > hi) {
int temp = hi;
hi = lo;
lo = temp;
}
return rnd.nextInt(hi-lo+1) + lo;
}
/**
* Returns the application version number as a String.
*
* @return A String representation of this application's version number.
*/
public static String version() { return VERSION; }
/**
* Returns a new string that is the leftmost n characters of String s, or
* the whole string if there are less than n characters, or an empty
* string if n is less than or equal to 0.
*
* @param s The String the characters will be copied from.
*
* @param n Determines how many characters will be copied from the
* leftmost part of string s.
*
* @return A String consisting of the leftmost n characters of s, or all
* of s if there are less than n characters in s.
*
*/
public static String left$(String s, int n) {
if (s == null) return "";
return n<=0 ? "" : s.substring(0, s.length()=s.length() || len<=0) ? "" :
s.substring(index, (len+index <= s.length()) ? len+index : s.length());
}
/**
* Returns a new string that is a substring of string s. The substring
* begins with the character at the specified index (the first character
* has an index of 0) and includes the remainder of the string.
* If index is less than 0 or greater than or equal to the length of the
* original string, then an empty string will be returned.
*
* @param s The String the characters will be copied from.
*
* @param index Determines where in string s to start copying characters.
*
* @return The right substring of s starting at index.
*
*/
public static String mid$(String s, int index) {
if (s == null) return "";
return mid$(s, index, s.length()-index);
}
/**
* Returns a string made up of n spaces. If n is less than or equal to
* 0, then a zero-length string is returned.
*
* @param n Specifies the number of spaces in the returned string.
*
* @return A String consisting of n spaces.
*
*/
public static String space$(int n) {
return repeat(' ', n);
}
/**
* Returns a string made up of n copies of character ch. If n is less
* than or equal to 0, then a zero-length string is returned.
*
* @param ch Specifies the character to be duplicated.
* @param n Specifies the number of duplicates to return.
*
* @return A String consisting of n copies of ch.
*
*/
public static String repeat(char ch, int n) {
if (n <= 0) return "";
StringBuilder sb = new StringBuilder();
while (n-- > 0) sb.append(ch);
return sb.toString();
}
/**
* Returns a string made up of n copies of String str. If n is less
* than or equal to 0, then a zero-length string is returned.
*
* @param str Specifies the string to be duplicated.
* @param n Specifies the number of duplicates to return.
*
* @return A String consisting of n copies of str.
*
*/
public static String repeat(String str, int n) {
if (n <= 0) return "";
StringBuilder sb = new StringBuilder();
while (n-- > 0) sb.append(str);
return sb.toString();
}
/**
* Returns a new string with leading whitespace removed.
*
* @param s The string to be processed.
*
* @return A copy of the String sent in with leading whitespace removed.
*
*/
public static String ltrim$(String s) {
if (s == null) return "";
StringBuilder sb = new StringBuilder(s);
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0)))
sb.deleteCharAt(0);
return sb.toString();
}
/**
* Returns a new string with trailing whitespace removed.
*
* @param s The string to be processed.
*
* @return A copy of the String sent in with trailing whitespace removed.
*
*/
public static String rtrim$(String s) {
if (s == null) return "";
StringBuilder sb = new StringBuilder(s);
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length()-1)))
sb.deleteCharAt(sb.length()-1);
return sb.toString();
}
/**
* Returns a new string with leading and trailing whitespace removed.
*
* @param s The string to be processed.
*
* @return A copy of the String sent in with leading and trailing whitespace removed.
*
*/
public static String trim$(String s) {
return s==null ? "" : ltrim$(rtrim$(s));
}
/**
* Returns a new string which is the upper case version of the string sent in.
*
* @param s The string to be made upper case.
*
* @return The uppercase equivalent of the String sent in.
*
*/
public static String ucase$(String s) { return s==null ? "" : s.toUpperCase(); }
/**
* Returns the upper case of a character.
*
* @param c The char to be made upper case.
*
* @return The uppercase equivalent of the character sent in.
*
*/
public static char ucase$(char c) { return Character.toUpperCase(c); }
/**
* Returns the upper case of a character.
*
* @param c The char to be made upper case.
*
* @return The uppercase equivalent of the character sent in.
*
*/
public static char ucase(char c) { return Character.toUpperCase(c); }
/**
* Returns a new string which is the lower case version of the string sent in.
*
* @param s The string to be made lower case.
*
* @return The lowercase equivalent of the String sent in.
*
*/
public static String lcase$(String s) { return s==null ? "" : s.toLowerCase(); }
/**
* Returns the lower case of a character.
*
* @param c The char to be made lower case.
*
* @return The lowercase equivalent of the character sent in.
*
*/
public static char lcase$(char c) { return Character.toLowerCase(c); }
/**
* Returns the lower case of a character.
*
* @param c The char to be made lower case.
*
* @return The lowercase equivalent of the character sent in.
*
*/
public static char lcase(char c) { return Character.toLowerCase(c); }
/**
* Displays a message in a graphical popup box.
*
* @param msg The message to be displayed.
*
*/
public static void alert(String msg) {
if (msg == null) return;
JOptionPane.showMessageDialog(null, msg);
}
/**
* Displays a message in a graphical popup box.
*
* @param msg The message to be displayed.
*
*/
public static void msgbox(String msg) { alert(msg); }
/**
* Displays a message in a graphical popup box and returns true
* if the user clicks OK and false otherwise. Also returns false
* is msg is null.
*
* @param msg The message to be displayed.
*
* @return True if user clicked OK, otherwise returns false.
*
*/
public static boolean confirm(String msg) {
if (msg == null) return false;
int n = JOptionPane.showConfirmDialog(null, msg);
return n==JOptionPane.YES_OPTION || n==JOptionPane.OK_OPTION;
}
/**
* Displays a message in a graphical popup box and returns
* the string typed in by the user, or a zero length string if
* nothing was typed in or the message box was canceled.
* Returns a zero-length string if the msg was null.
*
* @param msg The message to be displayed.
*
* @return The string typed in by the user, or a zero-length
* string if nothing was typed in or the dialig was canceled.
*/
public static String prompt(String msg) {
if (msg == null) return "";
return JOptionPane.showInputDialog(null, msg);
}
/**
* Displays a message in a graphical popup box and returns
* the boolean value typed in by the user.
*
* @param msg The prompt to be displayed.
*
* @return The boolean value typed in by the user.
*/
public static boolean promptBoolean(String msg) {
String msg2 = "Invalid entry. Re-enter.\n" + msg;
boolean valid = false;
while (!valid) {
String s = JOptionPane.showInputDialog(null, msg);
if (s != null) {
if (s.equalsIgnoreCase("TRUE")) return true;
if (s.equalsIgnoreCase("FALSE")) return false;
}
msg = msg2;
}
return false; // should never get here
}
/**
* Displays a message in a graphical popup box and returns
* the boolean value typed in by the user. This method uses
* a caller-supplied list of possible true and false values
* and returns it as a boolean value. The user supplied values
* are used case-insensitively.
*
* @param msg The prompt to be displayed.
*
* @param strTrue A comma-separated list of allowed true values.
*
* @param strFalse A comma-separated list of allowed false values.
*
* @return The boolean value typed in by the user.
*/
public static boolean promptBoolean(String msg, String strTrue, String strFalse) {
HashMap map = new HashMap();
StringTokenizer tok = new StringTokenizer(strTrue, ",");
while (tok.hasMoreTokens()) map.put(tok.nextToken().toUpperCase(), Boolean.TRUE);
tok = new StringTokenizer(strFalse, ",");
while (tok.hasMoreTokens()) map.put(tok.nextToken().toUpperCase(), Boolean.FALSE);
String msg2 = "Invalid entry. Re-enter.\n" + msg;
boolean valid = false;
while (!valid) {
String s = JOptionPane.showInputDialog(null, msg);
if (s != null) {
s = s.toUpperCase();
if (map.containsKey(s)) return map.get(s).booleanValue();
}
msg = msg2;
}
return false; // should never get here
}
/**
* Displays a message in a graphical popup box and returns
* the char value typed in by the user.
*
* @param msg The prompt to be displayed.
*
* @return The char value typed in by the user.
*/
public static char promptChar(String msg) {
String msg2 = "Invalid entry. Re-enter.\n" + msg;
char ch = ' ';
boolean valid = false;
while (!valid) {
String s = JOptionPane.showInputDialog(null, msg);
if (s != null && s.length() == 1) {
ch = s.charAt(0);
valid = true;
} else {
msg = msg2;
}
}
return ch;
}
/**
* Displays a message in a graphical popup box and returns
* the char value typed in by the user. The caller supplies
* both the prompt and the allowed responses.
*
* @param msg The prompt to be displayed.
*
* @param allowed The set of allowed responses.
*
* @return The char value typed in by the user.
*/
public static char promptChar(String msg, String allowed) {
String msg2 = "Invalid entry. Re-enter.\n" + msg;
char ch = ' ';
boolean valid = false;
while (!valid) {
String s = JOptionPane.showInputDialog(null, msg);
if (s != null && s.length() == 1) {
ch = s.charAt(0);
if (allowed.indexOf(ch) > -1) valid = true;
}
if (!valid) msg = msg2;
}
return ch;
}
/**
* Displays a prompt in a graphical popup box and returns
* the byte value typed in by the user.
*
* @param msg The prompt to be displayed.
*
* @return The byte value typed in by the user.
*/
public static byte promptByte(String msg) {
return promptByte(msg, Byte.MIN_VALUE, Byte.MAX_VALUE);
}
/**
* Displays a default prompt in a graphical popup box and
* returns the byte value typed in by the user.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The byte value typed in by the user.
*/
public static byte promptByte(byte lo, byte hi) {
return promptByte("Enter a value from " + lo + " to " + hi, lo, hi);
}
/**
* Displays a caller-supplied prompt in a graphical popup box and
* returns the byte value typed in by the user. The caller also
* supplies minimum and maximum values.
*
* @param msg The prompt to be displayed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The byte value typed in by the user.
*/
public static byte promptByte(String msg, byte lo, byte hi) {
byte temp = 0;
if (lo > hi) { temp = lo; lo = hi; hi = temp; }
long val = 0L;
String msg2 = msg;
boolean valid = false;
while (!valid) {
String s = JOptionPane.showInputDialog(null, msg2);
if (s != null) {
try {
val = Long.parseLong(s);
if (val < lo) msg2 = "Value too low (below " + lo + "). Please re-enter.\n" + msg;
else if (val > hi) msg2 = "Value too high (above " + hi + "). Please re-enter.\n" + msg;
else valid = true;
} catch (NumberFormatException e) {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
} else {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
}
return (byte) val;
}
/**
* Displays a default prompt in a graphical popup box and
* returns the byte value typed in by the user. The caller
* also supplies minimum and maximum values. This is a
* convenience method that allows int values to be used for
* the range values. An error message is displayed and the
* range modified to fit if needed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The byte value typed in by the user.
*/
public static byte promptByte(int lo, int hi) {
return promptByte("Enter a value from " + lo + " to " + hi, lo, hi);
}
/**
* Displays a caller-supplied prompt in a graphical popup box and
* returns the byte value typed in by the user. The caller also
* supplies minimum and maximum values. This is a
* convenience method that allows int values to be used for
* the range values. An error message is displayed and the
* range modified to fit if needed.
*
* @param msg The prompt to be displayed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The byte value typed in by the user.
*/
public static byte promptByte(String msg, int lo, int hi) {
boolean rangeError = false;
if (lo < Byte.MIN_VALUE) { rangeError = true; lo = Byte.MIN_VALUE; }
if (hi > Byte.MAX_VALUE) { rangeError = true; hi = Byte.MAX_VALUE; }
if (rangeError) alert("Internal error. Caller supplied range for\n"
+ "promptByte out of bounds!\nRange adjusted");
return promptByte(msg, (byte) lo, (byte) hi);
}
/**
* Displays a prompt in a graphical popup box and returns
* the short value typed in by the user.
*
* @param msg The prompt to be displayed.
*
* @return The short value typed in by the user.
*/
public static short promptShort(String msg) {
return promptShort(msg, Short.MIN_VALUE, Short.MAX_VALUE);
}
/**
* Displays a default prompt in a graphical popup box and
* returns the short value typed in by the user.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The short value typed in by the user.
*/
public static short promptShort(short lo, short hi) {
return promptShort("Enter a value from " + lo + " to " + hi, lo, hi);
}
/**
* Displays a caller-supplied prompt in a graphical popup box and
* returns the short value typed in by the user. The caller also
* supplies minimum and maximum values.
*
* @param msg The prompt to be displayed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The short value typed in by the user.
*/
public static short promptShort(String msg, short lo, short hi) {
short temp = 0;
if (lo > hi) { temp = lo; lo = hi; hi = temp; }
long val = 0L;
String msg2 = msg;
boolean valid = false;
while (!valid) {
String s = JOptionPane.showInputDialog(null, msg2);
if (s != null) {
try {
val = Long.parseLong(s);
if (val < lo) msg2 = "Value too low (below " + lo + "). Please re-enter.\n" + msg;
else if (val > hi) msg2 = "Value too high (above " + hi + "). Please re-enter.\n" + msg;
else valid = true;
} catch (NumberFormatException e) {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
} else {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
}
return (short) val;
}
/**
* Displays a default prompt in a graphical popup box and
* returns the short value typed in by the user. The caller
* also supplies minimum and maximum values. This is a
* convenience method that allows int values to be used for
* the range values. An error message is displayed and the
* range modified to fit if needed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The short value typed in by the user.
*/
public static short promptShort(int lo, int hi) {
return promptShort("Enter a value from " + lo + " to " + hi, lo, hi);
}
/**
* Displays a caller-supplied prompt in a graphical popup box and
* returns the short value typed in by the user. The caller also
* supplies minimum and maximum values. This is a
* convenience method that allows int values to be used for
* the range values. An error message is displayed and the
* range modified to fit if needed.
*
* @param msg The prompt to be displayed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The short value typed in by the user.
*/
public static short promptShort(String msg, int lo, int hi) {
boolean rangeError = false;
if (lo < Short.MIN_VALUE) { rangeError = true; lo = Short.MIN_VALUE; }
if (hi > Short.MAX_VALUE) { rangeError = true; hi = Short.MAX_VALUE; }
if (rangeError) alert("Internal error. Caller supplied range for\n"
+ "promptShort out of bounds!\nRange adjusted");
return promptShort(msg, (short) lo, (short) hi);
}
/**
* Displays a prompt in a graphical popup box and returns
* the int value typed in by the user.
*
* @param msg The prompt to be displayed.
*
* @return The int value typed in by the user.
*/
public static int promptInt(String msg) {
return promptInt(msg, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
/**
* Displays a default prompt in a graphical popup box and
* returns the int value typed in by the user.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The int value typed in by the user.
*/
public static int promptInt(int lo, int hi) {
return promptInt("Enter a value from " + lo + " to " + hi, lo, hi);
}
/**
* Displays a caller-supplied prompt in a graphical popup box and
* returns the int value typed in by the user. The caller also
* supplies minimum and maximum values.
*
* @param msg The prompt to be displayed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The int value typed in by the user.
*/
public static int promptInt(String msg, int lo, int hi) {
int temp = 0;
if (lo > hi) { temp = lo; lo = hi; hi = temp; }
long val = 0L;
String msg2 = msg;
boolean valid = false;
while (!valid) {
String s = JOptionPane.showInputDialog(null, msg2);
if (s != null) {
try {
val = Long.parseLong(s);
if (val < lo) msg2 = "Value too low (below " + lo + "). Please re-enter.\n" + msg;
else if (val > hi) msg2 = "Value too high (above " + hi + "). Please re-enter.\n" + msg;
else valid = true;
} catch (NumberFormatException e) {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
} else {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
}
return (int) val;
}
/**
* Displays a prompt in a graphical popup box and returns
* the long value typed in by the user.
*
* @param msg The prompt to be displayed.
*
* @return The long value typed in by the user.
*/
public static long promptLong(String msg) {
return promptLong(msg, Long.MIN_VALUE, Long.MAX_VALUE);
}
/**
* Displays a default prompt in a graphical popup box and
* returns the long value typed in by the user.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The long value typed in by the user.
*/
public static long promptLong(long lo, long hi) {
return promptLong("Enter a value from " + lo + " to " + hi, lo, hi);
}
/**
* Displays a caller-supplied prompt in a graphical popup box and
* returns the long value typed in by the user. The caller also
* supplies minimum and maximum values.
*
* @param msg The prompt to be displayed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The long value typed in by the user.
*/
public static long promptLong(String msg, long lo, long hi) {
long temp = 0;
if (lo > hi) { temp = lo; lo = hi; hi = temp; }
long val = 0L;
String msg2 = msg;
boolean valid = false;
while (!valid) {
String s = JOptionPane.showInputDialog(null, msg2);
if (s != null) {
try {
val = Long.parseLong(s);
if (val < lo) msg2 = "Value too low (below " + lo + "). Please re-enter.\n" + msg;
else if (val > hi) msg2 = "Value too high (above " + hi + "). Please re-enter.\n" + msg;
else valid = true;
} catch (NumberFormatException e) {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
} else {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
}
return (long) val;
}
/**
* Displays a default prompt in a graphical popup box and
* returns the long value typed in by the user. The caller
* also supplies minimum and maximum values. This is a
* convenience method that allows int values to be used for
* the range values. An error message is displayed and the
* range modified to fit if needed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The long value typed in by the user.
*/
public static long promptLong(int lo, int hi) {
return promptLong("Enter a value from " + lo + " to " + hi, lo, hi);
}
/**
* Displays a caller-supplied prompt in a graphical popup box and
* returns the long value typed in by the user. The caller also
* supplies minimum and maximum values. This is a
* convenience method that allows int values to be used for
* the range values. An error message is displayed and the
* range modified to fit if needed.
*
* @param msg The prompt to be displayed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The long value typed in by the user.
*/
public static long promptLong(String msg, int lo, int hi) {
return promptLong(msg, (long) lo, (long) hi);
}
/**
* Displays a prompt in a graphical popup box and returns
* the float value typed in by the user.
*
* @param msg The prompt to be displayed.
*
* @return The float value typed in by the user.
*/
public static float promptFloat(String msg) {
return promptFloat(msg, Float.MIN_VALUE, Float.MAX_VALUE);
}
/**
* Displays a default prompt in a graphical popup box and
* returns the float value typed in by the user.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The float value typed in by the user.
*/
public static float promptFloat(float lo, float hi) {
return promptFloat("Enter a value from " + lo + " to " + hi, lo, hi);
}
/**
* Displays a caller-supplied prompt in a graphical popup box and
* returns the float value typed in by the user. The caller also
* supplies minimum and maximum values.
*
* @param msg The prompt to be displayed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The float value typed in by the user.
*/
public static float promptFloat(String msg, float lo, float hi) {
float temp = 0;
if (lo > hi) { temp = lo; lo = hi; hi = temp; }
double val = 0.0;
String msg2 = msg;
boolean valid = false;
while (!valid) {
String s = JOptionPane.showInputDialog(null, msg2);
if (s != null) {
try {
val = Double.parseDouble(s);
if (val < lo) msg2 = "Value too low (below " + lo + "). Please re-enter.\n" + msg;
else if (val > hi) msg2 = "Value too high (above " + hi + "). Please re-enter.\n" + msg;
else valid = true;
} catch (NumberFormatException e) {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
} else {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
}
return (float) val;
}
/**
* Displays a default prompt in a graphical popup box and
* returns the float value typed in by the user. The caller
* also supplies minimum and maximum values. This is a
* convenience method that allows double values to be used for
* the range values. An error message is displayed and the
* range modified to fit if needed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The float value typed in by the user.
*/
public static float promptFloat(double lo, double hi) {
return promptFloat("Enter a value from " + lo + " to " + hi, lo, hi);
}
/**
* Displays a caller-supplied prompt in a graphical popup box and
* returns the float value typed in by the user. The caller also
* supplies minimum and maximum values. This is a
* convenience method that allows double values to be used for
* the range values. An error message is displayed and the
* range modified to fit if needed.
*
* @param msg The prompt to be displayed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The float value typed in by the user.
*/
public static float promptFloat(String msg, double lo, double hi) {
boolean rangeError = false;
if (lo < Float.MIN_VALUE) { rangeError = true; lo = Float.MIN_VALUE; }
if (hi > Float.MAX_VALUE) { rangeError = true; hi = Float.MAX_VALUE; }
if (rangeError) alert("Internal error. Caller supplied range for\n"
+ "promptFloat out of bounds!\nRange adjusted");
return promptFloat(msg, (float) lo, (float) hi);
}
/**
* Displays a prompt in a graphical popup box and returns
* the double value typed in by the user.
*
* @param msg The prompt to be displayed.
*
* @return The double value typed in by the user.
*/
public static double promptDouble(String msg) {
return promptDouble(msg, Double.MIN_VALUE, Double.MAX_VALUE);
}
/**
* Displays a default prompt in a graphical popup box and
* returns the double value typed in by the user.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The double value typed in by the user.
*/
public static double promptDouble(double lo, double hi) {
return promptDouble("Enter a value from " + lo + " to " + hi, lo, hi);
}
/**
* Displays a caller-supplied prompt in a graphical popup box and
* returns the double value typed in by the user. The caller also
* supplies minimum and maximum values.
*
* @param msg The prompt to be displayed.
*
* @param lo The minimum value allowed.
*
* @param hi The maximum value allowed.
*
* @return The double value typed in by the user.
*/
public static double promptDouble(String msg, double lo, double hi) {
double temp = 0;
if (lo > hi) { temp = lo; lo = hi; hi = temp; }
double val = 0.0;
String msg2 = msg;
boolean valid = false;
while (!valid) {
String s = JOptionPane.showInputDialog(null, msg2);
if (s != null) {
try {
val = Double.parseDouble(s);
if (val < lo) msg2 = "Value too low (below " + lo + "). Please re-enter.\n" + msg;
else if (val > hi) msg2 = "Value too high (above " + hi + "). Please re-enter.\n" + msg;
else valid = true;
} catch (NumberFormatException e) {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
} else {
msg2 = "Invalid input. Please re-enter.\n" + msg;
}
}
return val;
}
/**
* Displays a list of strings sent in as a set
* of menu choices and returns the choice the user
* selected as an int from 1 up to the number of
* choices sent in. It is important to remember to
* print any menu heading before this method is called
* and to add an "Exit" option as the last choice if
* applicable. A 0 is returned if there are no menu choices
* sent in.
*
* @param args These are the menu choices sent as Java
* String objects.
*
* @return The int value indicating what choice was made.
*
*/
public static int select(String... args) {
int limit = args.length;
if (limit == 0) return 0;
for (int i=0; i size) num = (int) (size-tot);
fos.write(buf, 0, num);
tot += size;
}
} catch (IOException e) {
failed = true;
} finally {
if (fis != null) try { fis.close(); } catch (IOException e) { }
if (fos != null) try { fos.close(); } catch (IOException e) { }
if (!failed) failed = !copyFile(dest.getAbsolutePath(), src.getAbsolutePath(), true);
}
return !failed;
}
/**
* Returns an array of strings representing the files and directories
* contained in the current user directory.
*
* @return An array of strings containg the files and directories
* in the current user directory.
*/
public static String[] dir() {
File f = new File(System.getProperty("user.dir"));
return f.list();
}
/**
* Returns an array of strings representing the files and directories
* contained in the designated user directory, or null if error.
*
* @param path The directory for which the listing is desired.
*
* @return An array of strings containg the files and directories
* in the specified directory, or null if error.
*/
public static String[] dir(String path) {
File f = new File(path);
if (!f.isDirectory() || !f.canRead()) return null;
return f.list();
}
/**
* Returns a string which is the path of the current user directory.
*
* @return A string which is the path of the current user directory.
*/
public static String getCurrentDirectory() {
return System.getProperty("user.dir");
}
/**
* Returns the number of arguments expected by a print formatting
* specification. Returns -1 if invalid specification string is found.
* Note that only obvious errors are found. If the supplied
* specification string contains an invalid type, such as %q, then
* this routine assumes it is valid as a new type might have been added.
*
* @param s The print formatting specification string.
*
* @return An int which is the number of expected arguments (-1 if error).
*/
private static int conversionSpecifiers(String s) {
String patspec = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";
Pattern pat = Pattern.compile(patspec);
Matcher m = pat.matcher(s);
int i = 0, numargs = 0, minargs = 0;
while (i < s.length()) {
if (m.find(i)) {
if (m.start() != i) {
if (s.substring(i, m.start()).indexOf('%') != -1) return -1;
}
String grpArgndx = m.group(1);
if (grpArgndx != null && grpArgndx.length() > 0) {
int argndx = Integer.parseInt(grpArgndx.substring(0, grpArgndx.length()-1));
if (argndx > minargs) minargs = argndx;
} else {
char type = m.group(6).charAt(0);
if (type != '%' && type != 'n') numargs++;
}
i = m.end();
} else {
if (s.substring(i).indexOf('%') != -1) return -1;
break;
}
}
return numargs>minargs ? numargs : minargs;
}
/**
* Used to create and use sequential access files in an easy way.
*
* Files are created using the SequentialFile constructor.
* Files written using the print methods are not field delimited
* by this class and are meant to be read back in using the
* readLine method which reads in a whole line up to the next
* newline. Files written using the write methods are delimited
* by commas between fields and newlines at the ends of records.
* They are expected to be read using the various readType###
* methods, where Type is the data type of the field
* being read in.
*
* @author David G. Klick
* @version 10/31/2007
*/
public static class SequentialFile {
private final FileMode filemode;
private final String filename;
private final File file;
private long fileLength = 0;
private long filePosition = 0;
private FileInputStream fistream = null;
private FileOutputStream fostream = null;
private boolean beginningOfLine = true;
private boolean eof = true;
/**
* Opens a file for sequential access input or output.
*
* The available modes are INPUT, OUTPUT, and APPEND.
* They are all available as members of FileMode. INPUT
* allows reading from the start of a file, OUTPUT writes
* to a file starting at the beginning, and APPEND writes
* to a file starting at the end. OUTPUT erases any previous
* data. APPEND preserves previous data.
*
* @param filename the name of the file, including the path
* if the file is not in the current directory
* @param mode one of FileMode.INPUT, FileMode.OUTPUT,
* or FileMode.APPEND
*/
public SequentialFile(String filename, FileMode mode) {
this.filename = filename;
filemode = mode;
file = new File(filename);
switch (filemode) {
case INPUT:
if (!file.exists()) {
errorExit("Input file does not exist");
}
if (!file.isFile() || !file.canRead()) {
errorExit("Can not open file for input");
}
try {
fistream = new FileInputStream(file);
if (file.length() > 0) eof = false;
} catch (IOException e) {
errorExit("Can not open file for input");
}
fileLength = file.length();
filePosition = 1L;
break;
case OUTPUT:
if (file.exists() && !file.canWrite()) {
errorExit("Can not write to output file");
}
try {
fostream = new FileOutputStream(file, false);
} catch (IOException e) {
errorExit("Can not open file for output");
}
eof = true;
beginningOfLine = true;
fileLength = 0L;
filePosition = 1L;
break;
case APPEND:
if (file.exists() && !file.canWrite()) {
errorExit("Can not write to output file");
}
try {
// need to determine beginningOfLine status
if (file.exists() && file.length()>0) {
fistream = new FileInputStream(file);
fistream.skip(file.length()-1);
int n = fistream.read();
beginningOfLine = (n == '\n') ? true : false;
fistream.close();
fistream = null;
} else {
beginningOfLine = true;
}
fostream = new FileOutputStream(file, true);
} catch (IOException e) {
errorExit("Can not open file for append");
}
eof = true;
fileLength = file.length();
filePosition = fileLength + 1;
break;
default:
errorExit("Unrecognized file mode");
break;
}
}
private void errorExit(String msg) {
System.out.println("Error: " + msg);
System.exit(0);
}
private String escape(String s) {
StringBuilder sb = new StringBuilder();
for (int i=0; i fileLength) eof = true;
} catch (IOException e) {
errorExit("Problem reading character from file: " + file.getName());
}
return n;
}
private String freadField() {
StringBuilder sb = new StringBuilder();
final int INIT = 0;
final int QUOTED = 1;
final int ESCAPE = 2;
final int EATDELIM = 3;
final int NONQUOTED = 4;
final int DONE = 5;
final int ERROR = 6;
int mode = INIT;
int c;
if (eof()) errorExit("Attempt to read past end of file: " + file.getName());
while (mode != DONE && mode != ERROR) {
c = freadChar();
if (c == -1) {
if (sb.length() == 0) errorExit("Read past end of file");
mode = DONE;
}
switch (mode) {
case INIT:
if (c=='\r') ; //ignore CR
else if (c=='\n' || c==',') mode = DONE;
else if (c == '"') mode = QUOTED;
else {
sb.append((char) c);
mode = NONQUOTED;
}
break;
case QUOTED:
if (c == -1) {
eof = true;
mode = ERROR;
errorExit("Read invalid field from file: " + file.getName());
} else if (c == '\\') {
mode = ESCAPE;
} else if (c == '"') {
if (filePosition < fileLength) mode = EATDELIM;
else mode = DONE;
} else sb.append((char) c);
break;
case ESCAPE:
if (c == -1) {
eof = true;
mode = ERROR;
errorExit("Read invalid field from file: " + file.getName());
} else {
sb.append('\\');
sb.append((char) c);
mode = QUOTED;
}
break;
case NONQUOTED:
if (c == -1) {
eof = true;
mode = DONE;
} else if (c=='\n' || c==',') mode = DONE;
else if (c == '\r'); // ignore
else sb.append((char) c);
break;
case EATDELIM:
if (c!='\r') {
if (c!='\n' && c!=',' && c!=-1) {
mode = ERROR;
errorExit("Invalid delimiter read from file: " + file.getName());
} else if (c == -1) eof = true;
mode = DONE;
}
break;
case DONE: break;
case ERROR: // should never get here
default: // should never get here
errorExit("Internal error while reading file: " + file.getName());
break;
}
}
if (filePosition >= fileLength) eof = true;
return sb.toString();
}
private void fwrite(char c) {
try {
fostream.write(c);
fileLength++;
filePosition++;
} catch (IOException e) {
errorExit("Problem writing to file");
}
}
private void fwrite(String s) {
for (int i=0; i 2) {
errorExit("Invalid character read from file: " + file.getName());
} else if (s.length() == 2) {
char c1 = s.charAt(0);
char c2 = s.charAt(1);
if (c1 != '\\') {
errorExit("Invalid character read from file: " + file.getName());
} else if (c2 == 'n') {
c = '\n';
} else if (c2 == 'r') {
c = '\r';
} else if (c2 == 't') {
c = '\t';
} else if (c2 == 'b') {
c = '\b';
} else if (c2 == 'f') {
c = '\f';
} else if (c2 == '"') {
c = '"';
} else if (c2 == '\\') {
c = '\\';
} else {
errorExit("Invalid escape character read from file: " + file.getName());
}
} else {
c = s.charAt(0);
}
return c;
}
/**
* Reads a double value from the file.
*
* @return the double value read from the file
*/
public double readDouble() {
double result = 0;
String s = freadField();
try {
s = s.trim();
if (s.length() == 0) s = "0";
result = Double.parseDouble(s);
} catch (NumberFormatException e) {
errorExit("Invalid double read from file: " + file.getName());
}
return result;
}
/**
* Reads a float value from the file.
*
* @return the float value read from the file
*/
public float readFloat() {
float result = 0.0f;
String s = freadField();
try {
s = s.trim();
if (s.length() == 0) s = "0";
result = Float.parseFloat(s);
} catch (NumberFormatException e) {
errorExit("Invalid float read from file: " + file.getName());
}
return result;
}
/**
* Reads an int value from the file.
*
* @return the int value read from the file
*/
public int readInt() {
int result = 0;
String s = freadField();
try {
s = s.trim();
if (s.length() == 0) s = "0";
result = Integer.parseInt(s);
} catch (NumberFormatException e) {
errorExit("Invalid integer read from file: " + file.getName());
}
return result;
}
/**
* Reads an entire line up to a newline from the file.
*
* @return the line read from the file
*/
public String readLine() {
StringBuilder sb = new StringBuilder();
int c = 0;
if (eof()) errorExit("Attempt to read past end of file: " + file.getName());
while (!eof() && c != '\n') {
c = freadChar();
if (c == -1) {
if (eof()) errorExit("Attempt to read past end of file: " + file.getName());
eof = true;
} else {
if (c != '\n') sb.append((char) c);
}
}
return sb.toString();
}
/**
* Reads a long value from the file.
*
* @return the long value read from the file
*/
public long readLong() {
long result = 0;
String s = freadField();
try {
s = s.trim();
if (s.length() == 0) s = "0";
result = Long.parseLong(s);
} catch (NumberFormatException e) {
errorExit("Invalid long read from file: " + file.getName());
}
return result;
}
/**
* Reads a short value from the file.
*
* @return the short value read from the file
*/
public short readShort() {
short result = 0;
String s = freadField();
try {
s = s.trim();
if (s.length() == 0) s = "0";
result = Short.parseShort(s);
} catch (NumberFormatException e) {
errorExit("Invalid short read from file: " + file.getName());
}
return result;
}
/**
* Reads a quoted String from the file.
*
* @return the String read from the file
*/
public String readString() {
String s = freadField();
return unescape(s);
}
/**
* Writes a list of fields to a file separated by commas.
*
* @param fields the list of fields to be written to the file
*/
public void write(Object... fields) {
String cname = "";
for (Object field : fields) {
Class c = field.getClass();
cname = c.getName();
if (!beginningOfLine) fwrite(',');
boolean primitive = cname.matches("java\\.lang\\."
+ "(Byte|Short|Integer|Long|Float|Double|Boolean)");
if (primitive) {
fwrite(field.toString());
} else {
fwrite("\"" + escape(field.toString()) + "\"");
}
beginningOfLine = false;
}
}
/**
* Writes a list of fields to a file separated by commas
* and terminated with a newline.
*
* @param fields the list of fields to be written to the file
*/
public void writeln(Object... fields) {
write(fields);
fwrite('\n');
beginningOfLine = true;
}
}
/**
* Used to create and use random access files in an easy way.
*
* A class must be provided to the constructor to specify what
* fields are in a record. All instance and static fields in the class
* are considered specifiers for fields in the record. Private, protected,
* and final fields are considered invalid. String-type fields must be a
* fixed-length, so whatever the length a String is in the original record
* is assumed to be the length of the String in all subsequent reads or
* writes. String, StringBuffer, StringBuilder, and all the built-in data
* types are allowed in a record.
* The ability to use primitive data types in arrays within the
* random access record added on 3/16/2008.
*
* @author David G. Klick
* @version 3/16/2008
*/
public static class RandomFile {
private enum FieldType { BYTE, SHORT, INTEGER, LONG, BOOLEAN,
FLOAT, DOUBLE, CHARACTER, STRING, STRINGBUILDER, STRINGBUFFER,
BYTEARRAY, SHORTARRAY, INTEGERARRAY, LONGARRAY, BOOLEANARRAY,
FLOATARRAY, DOUBLEARRAY, CHARACTERARRAY,};
private final String filename;
private final File file;
private int recordLength = 0;
private long fileLength = 0;
private RandomAccessFile rndfile = null;
private boolean eof = true;
private T rec = null;
private Field[] fields = null;
private class FieldInfo {
Field field;
FieldType type;
int length;
int arrayLength; // only used if field is an array
}
private Vector fieldinfo = null;
protected void close() {
if (rndfile != null) {
try {
rndfile.close();
rndfile = null;
} catch (IOException e) {}
}
}
private void errorExit(String msg) {
System.out.println("Error: " + msg);
System.exit(0);
}
protected void finalize() {
try {
if (rndfile != null) {
System.out.println("You forgot to close the file: " + file.getName());
rndfile.close();
}
} catch (IOException e) {}
}
private String resizeString(String s, int len) {
int i = 0;
StringBuilder sb = new StringBuilder();
for (i=0; i= len) break;
sb.append(s.charAt(i));
}
while (i < len) { sb.append(' '); i++; }
return sb.toString();
}
/**
* Opens a file for random access input and output.
*
* A class must be provided to the constructor to specify what
* fields are in a record. All instance and static fields in the class
* are considered specifiers for fields in the record. Private, protected,
* and final fields are considered invalid. String-type fields must be a
* fixed-length, so whatever the length a String is in the original record
* is assumed to be the length of the String in all subsequent reads or
* writes. String, StringBuffer, StringBuilder, and all the built-in data
* types are allowed in a record.
*
* @param filename The name of the file, including the path
* if the file is not in the current directory
* @param rec A record used as a prototype to specify field types and sizes
*/
@SuppressWarnings(value = "unchecked")
public RandomFile(String filename, T rec) {
this.filename = filename;
file = new File(filename);
try {
this.rec = (T) (rec.getClass().newInstance());
} catch (Exception e) {
errorExit("Error: Could not open file due to class error");
}
Class c = rec.getClass();
fields = c.getDeclaredFields();
if (fields.length < 1) {
errorExit("Random file record must have at least one field");
}
fieldinfo = new Vector();
for (int i=0; i The object type to be returned
* @param recnum The number of the record to be retrieved; numbering
* starts at 1
*
* @return A record containg the data retrieved from the file
*/
@SuppressWarnings("unchecked")
public T get(long recnum) {
String s = null, tmp = null;
T rec = null;
try {
rec = (T) (this.rec.getClass().newInstance());
} catch (Exception e) {
errorExit("Error: Could not open file due to class error");
}
if ((recnum > numberOfRecords()) || (recnum <= 0)) {
errorExit("Invalid record number specified in random access read");
}
try {
rndfile.seek((recnum-1)*recordLength);
byte[] buf;
for (int i=0; i numberOfRecords() + 1) || (recnum <= 0)) {
errorExit("Invalid record number specified in random access write");
}
if (recnum > numberOfRecords()) newRecord = true;
try {
rndfile.seek((recnum-1)*recordLength);
for (int i=0; i