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:

*
    *
  1. Clearing the console window in Windows from Java is * non-obvious. Solutions include: *
      *
    1. 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
    2. *
    3. 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
    4. *
    5. 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
    6. *
    7. 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
    8. *
*

* 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