/* * @(#)DummiesIO.java 08/04/2003 * * Copyright 2003 John Wiley & Sons, Inc. All Rights Reserved. *

This code complements the material in the book "Beginning * Programming with Java For Dummies." For another version of * DummiesIO.java (a version that complements the book "Java 2 * For Dummies," visit http://www.BurdBrain.com/. * * This code is preliminary. * Visit http://www.BurdBrain.com/ again for updates. */ import java.io.*; import java.util.StringTokenizer; import java.util.Hashtable; /** * This class implments simple text-based input and output * for the keyboard and for disk files. For examples of the use of * methods in this class, see Beginning Programming with For Dummies by Barry * Burd, ©2003 John Wiley & Sons, Inc. *

Most of the methods in this class are * getType methods, print methods, or * println methods. For instance, * to read an int value from the keyboard, call *

   intVariable = DummiesIO.getInt();
* To read an int value from a file * named myFile.txt, call *
   intVariable = DummiesIO.getInt("myFile.txt");
*

A disk file's name can be relative to the directory containing the code * (as in "myFile.txt"). Alternatively, the file name can * be absolute, as in *

   intVariable = DummiesIO.getInt("c:\\JavaPrograms\\myFiletxt");
* For absolute file names in Windows, be sure to use two backslashes in * place of each single backslash (as file separators). *

(Note: Supplying file name strings to input/output methods is unique * to this DummiesIO program. With real, industrial-strength IO programs, you generally * don't use file-name strings to refer to files.) *

To read several values, one after another, separate the values with any * number of blank spaces and/or any number of newlines. For instance, to * read the number 23 followed by the word Hello * from the keyboard, use the following Java code: *

   intVariable = DummiesIO.getInt();
 *   stringVariable = DummiesIO.getString();
* You can enter the input on the keyboard in any of the following ways: *
23 Hello
*
*
23     Hello
*
*
     23
 *
 *
 *    Hello
*
*
23
 * Hello
*
* To write the value 77 to a file named myOutput.txt, * call *
   DummiesIO.print("myOutput.txt", 77);
* To write the value 77 to the same file, and to go to the next line * after writing that value, call *
   DummiesIO.println("myOutput.txt", 77);
* The latter call to println is equivalent to the following two calls: *
   DummiesIO.print("myOutput.txt", 77);
 *   DummiesIO.println("myOutput.txt");
* @author Barry Burd */ public class DummiesIO { private static Hashtable hashtable = new Hashtable(); private static BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in)); private static boolean isForgiving=false; static { hashtable.put("keyboard", new InFileState(keyboard)); } private DummiesIO() {} /** * With forgiving set to true, * DummiesIO is generally more willing to continue running * when it encounters an IO error. For example, if you call getInt(), the user types * a letter rather than an integer, and forgiving is true, then the call to getInt() * returns the value 0, and the program continues to run. By default, forgiving is false. * @param value Either true for forgiving, or false for unforgiving */ public static void setForgiving (boolean value) { isForgiving=value; } private static InFileState openOrUseExisting (String fileName) { InFileState inFileState=null; try { inFileState = (InFileState)hashtable.get(fileName); } catch (ClassCastException e) { System.out.println("Warning: You are reading from a file to which you've already"); System.out.println("written data (file: " + fileName + ")."); System.out.println("Subsequent write operations to this file will delete any"); System.out.println("data that you've already written."); } if (inFileState == null) { getFileForReading(fileName); inFileState = (InFileState)hashtable.get(fileName); } return inFileState; } private static void fillTokenBuffer (InFileState inFileState) { String tempLineBuffer = null; while (inFileState.tokenizer==null || !inFileState.tokenizer.hasMoreTokens()) { try { tempLineBuffer = inFileState.reader.readLine(); } catch (IOException e) { System.out.println("Cannot read the next value."); e.printStackTrace(); } if (tempLineBuffer != null) { inFileState.tokenizer = new StringTokenizer(tempLineBuffer, " ", true); } else { inFileState.isAtEOF = true; break; } } try { inFileState.tokenBuffer = inFileState.tokenizer.nextToken(); } catch (Exception e) { inFileState.tokenBuffer = ""; } } /** * Tests to see if you've reached the end of a particular disk file. * If so, the method returns true. Otherwise the method * returns false. For instance, to find out if you've read * up to the very end of myFile.txt check *
   if (DummiesIO.endOfFile("myFile.txt")) ... Etc.
* @param fileName The name of a file * @return true if you've reached the end of the file, and false otherwise */ public static boolean endOfFile(String fileName) { InFileState inFileState = openOrUseExisting(fileName); while ((inFileState.tokenBuffer == null || inFileState.tokenBuffer.equals("")) && !inFileState.isAtEOF) fillTokenBuffer(inFileState); return inFileState.isAtEOF; } private static String getNonblankToken(String fileName) { InFileState inFileState = openOrUseExisting(fileName); String tempTokenBuffer = null; while (inFileState.tokenBuffer == null || inFileState.tokenBuffer.equals(" ") && !inFileState.isAtEOF) fillTokenBuffer(inFileState); try { if (inFileState.isAtEOF) throw new EOFException(); } catch (EOFException e) { System.out.println("No more data in the file."); e.printStackTrace(); System.exit(1); } tempTokenBuffer = inFileState.tokenBuffer; inFileState.tokenBuffer = null; return tempTokenBuffer; } private static char getCharFromToken (String fileName) { InFileState inFileState = openOrUseExisting(fileName); char tempCharBuffer; while ((inFileState.tokenBuffer==null || inFileState.tokenBuffer.length()==0) && !inFileState.isAtEOF) { fillTokenBuffer(inFileState); } try { if (inFileState.isAtEOF) throw new EOFException(); } catch (EOFException e) { System.out.println("No more data in the file."); e.printStackTrace(); System.exit(1); } tempCharBuffer = inFileState.tokenBuffer.charAt(0); if (inFileState.tokenBuffer.length()>=2) { inFileState.tokenBuffer = inFileState.tokenBuffer.substring(1); } else { inFileState.tokenBuffer = null; } return tempCharBuffer; } private static String getRestOfLine(String fileName) { InFileState inFileState = openOrUseExisting(fileName); StringBuffer tempLine = new StringBuffer(); while (inFileState.tokenBuffer==null || inFileState.tokenBuffer.length()==0 && !inFileState.isAtEOF) fillTokenBuffer(inFileState); try { if (inFileState.isAtEOF) throw new EOFException(); } catch (EOFException e) { System.out.println("No more data in the file."); e.printStackTrace(); System.exit(1); } tempLine.append(inFileState.tokenBuffer); inFileState.tokenBuffer = null; while (inFileState.tokenizer.hasMoreTokens()) tempLine.append(inFileState.tokenizer.nextToken()); inFileState.tokenizer = null; return new String(tempLine); } private static void getFileForReading(String string) { FileInputStream f=null; try { f = new FileInputStream (string); } catch (FileNotFoundException e) { e.printStackTrace(); System.exit(1); } InputStreamReader inp = new InputStreamReader(f); BufferedReader b = new BufferedReader(inp); hashtable.put(string, new InFileState(b)); } /** * Reads an int value from the keyboard. At the keyboard, * the user types a sequence of digits, optionally preceded by a minus * sign. * @return The int value typed on the keyboard by the user * @see #getInt(java.lang.String) */ static public int getInt() { return getInt("keyboard"); } /** * Reads an int value from a disk file * @param fileName The name of a file * @return The int value found in the file * @see #getInt() */ static public int getInt(String fileName) { String token=""; try { return Integer.parseInt(token=getNonblankToken(fileName)); } catch (Exception e) { System.out.println("Cannot read an int value."); System.out.print("Expected an int value;"); System.out.println(" Received >>" + token + "<< instead."); e.printStackTrace(); if (!isForgiving) System.exit(1); return 0; } } /** * Reads a double value from the keyboard. At the keyboard, * the user types a double literal. Examples of double literals include *
   1e1   2.   .3   0.0   3.14   1e-9d
* @return The double value typed on the keyboard by the user * @see #getDouble(java.lang.String) */ static public double getDouble() { return getDouble("keyboard"); } /** * Reads a double value from a disk file * @param fileName The name of a file * @return The double value found in the file * @see #getDouble() */ static public double getDouble(String fileName) { String token=""; try { return Double.parseDouble(token=getNonblankToken(fileName)); } catch (Exception e) { System.out.println("Cannot read a double value."); System.out.print("Expected a double value;"); System.out.println(" Received >>" + token + "<< instead."); e.printStackTrace(); if (!isForgiving) System.exit(1); return 0.0; } } /** * Reads a char value from the keyboard. At the keyboard, * the user types a single character. The character * can be a letter, a digit, a punctuation symbol, or whatever. * In typing the character, the user does not surround the character * with quote marks (as you would in typing a character literal in * a Java program). *

Unlike other DummiesIO.get * methods, the getChar method does not expect blank spaces to * separate one value from another. For instance, the following code *

   char1 = DummiesIO.getChar();
   *   char2 = DummiesIO.getChar();
   *   char3 = DummiesIO.getChar();
* with the following input *
   xyz
* will put x in the variable char1, y in * the variable char2, and z in the variable char3. * With the following (slightly different) input *
   x y z
* and the same three calls to getChar, the value of char1 will be * x, but char2 will contain a blank space, and the value of * char3 will be y. * @return The char value typed on the keyboard by the user * @see #getChar(java.lang.String) */ static public char getChar() { return getChar("keyboard"); } /** * Reads a char value from a disk file * @param fileName The name of a file * @return The char value found in the file * @see #getChar() */ static public char getChar(String fileName) { char token=' '; try { return token=getCharFromToken(fileName); } catch (Exception e) { System.out.println("Cannot read a char value."); System.out.print("Expected a char value;"); System.out.print(" Received >>"); System.out.print(token); System.out.println("<< instead."); e.printStackTrace(); if (!isForgiving) System.exit(1); return ' '; } } /** * Reads a boolean value from the keyboard. Returns * true if the user types true; returns false otherwise. * The input is not case sensitive. (The method returns true if the * user types tRuE.) * @return The boolean value typed on the keyboard by the user * @see #getBoolean(java.lang.String) */ static public boolean getBoolean() { return getBoolean("keyboard"); } /** * Reads a boolean value from a disk file * @param fileName The name of a file * @return The boolean value found in the file * @see #getBoolean() */ static public boolean getBoolean(String fileName) { String token=""; try { return (Boolean.valueOf(token=getNonblankToken(fileName))).booleanValue(); } catch (Exception e) { System.out.println("Cannot read a boolean value."); System.out.print("Expected a boolean value;"); System.out.println(" Received >>" + token + "<< instead."); e.printStackTrace(); if (!isForgiving) System.exit(1); return false; } } /** * Reads a string of characters from the keyboard. At the keyboard, * the user types a sequence of characters followed by a blank space or by * the end of a line. In typing the sequence of characters, * the user does not surround these characters * with quote marks (as you would in typing a String literal in * a Java program). * @return The next sequence of characters typed on the keyboard by the user (up to but not including the first blank space or the end of a line) * @see #getString(java.lang.String) * @see #getLine() * @see #getLine(java.lang.String) */ static public String getString() { return getString("keyboard"); } /** * Reads a string of characters (up to the next blank space or the end of a line) from a disk file * @param fileName The name of a file * @return The next sequence of characters from a disk file (up to but not including the first blank space or the end of a line) * @see #getString() */ static public String getString(String fileName) { String token=""; try { return token=getNonblankToken(fileName); } catch (Exception e) { System.out.println("Cannot read a String value."); System.out.print("Expected a String value;"); System.out.println(" Received >>" + token + "<< instead."); e.printStackTrace(); if (!isForgiving) System.exit(1); return ""; } } /** * This method (which is not yet working correctly) is meant to read a byte * (eight bits) from the keyboard. * @return a byte value * @see #getByte(java.lang.String) */ static private byte getByte() { return getByte("keyboard"); } /** * This method (which is not yet working correctly) is meant to read a byte * (eight bits) from a disk file. * @param fileName The name of a file * @return The byte value found in the file * @see #getByte() */ static private byte getByte(String fileName) { try { ///THIS METHOD ISN'T FINISHED BEING WRITTEN YET return Byte.parseByte(getNonblankToken(fileName)); } catch (Exception e) { System.out.println("Cannot read a byte value."); e.printStackTrace(); if (!isForgiving) System.exit(1); return (byte)0; } } /** * Reads a short value from the keyboard. At the keyboard, * the user types a sequence of digits, optionally preceded by a minus * sign. * @return The short value typed on the keyboard by the user * @see #getShort(java.lang.String) */ static public short getShort() { return getShort("keyboard"); } /** * Reads a short value from a disk file * @param fileName The name of a file * @return The short value found in the file * @see #getShort() */ static public short getShort(String fileName) { String token=""; try { return Short.parseShort(token=getNonblankToken(fileName)); } catch (Exception e) { System.out.println("Cannot read a short value."); System.out.print("Expected a short value;"); System.out.println(" Received >>" + token + "<< instead."); e.printStackTrace(); if (!isForgiving) System.exit(1); return (short)0; } } /** * Reads a long value from the keyboard. At the keyboard, * the user types a sequence of digits, optionally preceded by a minus * sign. The user does not type the letter L or * l, as you would for a long literal in a * Java program. * @return The long value typed on the keyboard by the user * @see #getLong(java.lang.String) */ static public long getLong() { return getLong("keyboard"); } /** * Reads a long value from a disk file * @param fileName The name of a file * @return The long value found in the file * @see #getLong() */ static public long getLong(String fileName) { String token=""; try { return Long.parseLong(token=getNonblankToken(fileName)); } catch (Exception e) { System.out.println("Cannot read a long value."); System.out.print("Expected a long value;"); System.out.println(" Received >>" + token + "<< instead."); e.printStackTrace(); if (!isForgiving) System.exit(1); return 0L; } } /** * Reads a float value from the keyboard. At the keyboard, * the user types a float literal. Examples of float literals include *
   1e1f   2.f   .3f   0f   3.14f   6.022137e+23f
* @return The float value typed on the keyboard by the user * @see #getFloat(java.lang.String) */ static public float getFloat() { return getFloat("keyboard"); } /** * Reads a float value from a disk file * @param fileName The name of a file * @return The float value found in the file * @see #getFloat() */ static public float getFloat(String fileName) { String token=""; try { return Float.parseFloat(token=getNonblankToken(fileName)); } catch (Exception e) { System.out.println("Cannot read a float value."); System.out.print("Expected a float value;"); System.out.println(" Received >>" + token + "<< instead."); e.printStackTrace(); if (!isForgiving) System.exit(1); return 0.0F; } } /** * Reads the remaining line (up to the pressing of the Enter key) from the keyboard. * This method reads past blank spaces. For instance, if the user types *
   Hello, how are you?
* then one call to the getLine method gets all four words and the * two punctuation symbols.

This method doesn't necessarily read an entire line from * beginning to end. Instead, the method can read from a point in the middle of a line to * the end of the line. For example, if the user types the following: *

   42 Hello there!
   *   Goodbye! 88
* and the Java program calls *
   x = getInt();
   *   y = getLine();
   *   z = getLine();
* then the value of x is 42, the value of y is * "Hello there!", and the value of z is "Goodbye! 88". * @return The next sequence of characters typed on the keyboard by the user (up to the user's pressing of the Enter key) * @see #getLine(java.lang.String) * @see #getString() * @see #getString(java.lang.String) */ static public String getLine() { return getLine("keyboard"); } /** * Reads the remaining line (up to the start of a new line) from a disk file. * @param fileName The name of a file * @return The next sequence of characters found in the file (up to the end of the current line) * @see #getLine() */ static public String getLine(String fileName) { try { return getRestOfLine(fileName); } catch (Exception e) { System.out.println("Cannot read the rest of the line."); e.printStackTrace(); if (!isForgiving) System.exit(1); return ""; } } /** * Writes the word true or the word false to a disk file. * After writing the word, this method goes to the next line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The boolean value that's to be written to the file * @see #print(java.lang.String, boolean) */ public static void println(String fileName, boolean value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.println(value); } /** * Writes the word true or the word false to a disk file. * After writing the word, this method remains on the same line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The boolean value that's to be written to the file * @see #println(java.lang.String, boolean) */ public static void print(String fileName, boolean value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.print(value); } /** * Writes a single character (without single quote marks) to a disk file. * After writing the character, this method goes to the next line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The char value that's to be written to the file * @see #print(java.lang.String, char) */ public static void println(String fileName, char value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.println(value); } /** * Writes a single character (without single quote marks) to a disk file. * After writing the character, this method remains on the same line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The char value that's to be written to the file * @see #println(java.lang.String, char) */ public static void print(String fileName, char value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.print(value); } /** * Writes a double value to a disk file. * After writing the value, this method goes to the next line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The double value that's to be written to the file * @see #print(java.lang.String, double) */ public static void println(String fileName, double value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.println(value); } /** * Writes a double value to a disk file. * After writing the value, this method remains on the same line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The double value that's to be written to the file * @see #println(java.lang.String, double) */ public static void print(String fileName, double value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.print(value); } /** * Writes a float value to a disk file. * After writing the value, this method goes to the next line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The float value that's to be written to the file * @see #print(java.lang.String, float) */ public static void println(String fileName, float value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.println(value); } /** * Writes a float value to a disk file. * After writing the value, this method remains on the same line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The float value that's to be written to the file * @see #println(java.lang.String, float) */ public static void print(String fileName, float value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.print(value); } /** * Writes an int value to a disk file. * After writing the value, this method goes to the next line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The int value that's to be written to the file * @see #print(java.lang.String, int) */ public static void println(String fileName, int value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.println(value); } /** * Writes an int value to a disk file. * After writing the value, this method remains on the same line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The int value that's to be written to the file * @see #println(java.lang.String, int) */ public static void print(String fileName, int value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.print(value); } /** * Writes a long to a disk file. * After writing the value, this method goes to the next line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The long value that's to be written to the file * @see #print(java.lang.String, long) */ public static void println(String fileName, long value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.println(value); } /** * Writes a long to a disk file. * After writing the value, this method remains on the same line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The long value that's to be written to the file * @see #println(java.lang.String, long) */ public static void print(String fileName, long value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.print(value); } /** * Writes a string of characters to a disk file. This method does not add * double quote marks to the beginning and end of the string (and for most purposes, * there's no reason to * surround the string with double quote marks). * After writing the string, this method goes to the next line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The String value that's to be written to the file * @see #print(java.lang.String, java.lang.String) */ public static void println(String fileName, String value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.println(value); } /** * Writes a string of characters to a disk file. This method does not add * double quote marks to the beginning and end of the string (and for most purposes, * there's no reason to * surround the string with double quote marks). * After writing the value, this method remains on the same line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file * @param value The String value that's to be written to the file * @see #println(java.lang.String, java.lang.String) */ public static void print(String fileName, String value) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.print(value); } /** * Writes no visible text to a disk file, but goes to the next line in the disk file * (in preparation for any subsequent print or println calls * that write to this file). * @param fileName The name of a file */ public static void println(String fileName) { OutFileState outFileState = openForWriteOrUseExisting(fileName); outFileState.printStream.println(); } private static OutFileState openForWriteOrUseExisting (String fileName) { OutFileState outFileState=null; try { outFileState = (OutFileState)hashtable.get(fileName); } catch (ClassCastException e) { System.out.println("Warning: You are writing to a file from which you've already"); System.out.println("read data (file: " + fileName + ")."); System.out.println("Write operations to this file will delete any data in the"); System.out.println("file."); } if (outFileState == null) { getFileForWriting(fileName); outFileState = (OutFileState)hashtable.get(fileName); } return outFileState; } private static void getFileForWriting(String string) { FileOutputStream f=null; try { f = new FileOutputStream(string); } catch (FileNotFoundException e) { e.printStackTrace(); System.exit(1); } PrintStream p = new PrintStream(f); hashtable.put(string, new OutFileState(p)); } } class InFileState { BufferedReader reader = null; StringTokenizer tokenizer = null; String tokenBuffer = null; boolean isAtEOF = false; InFileState(BufferedReader reader) { this.reader = reader; } } class OutFileState { PrintStream printStream; OutFileState(PrintStream printStream) { this.printStream=printStream; } }