import java.io.Closeable; import java.io.InputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.util.InputMismatchException; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Scanner; /** * An iterator class to input specific data types from an input stream without throwing any * exceptions. If there are any errors during use of the iterator then a message is output to * the standard output and the program terminates. *

*

This is just a simple wrapper around Scanner that implements a subset of the * Scanner public interface.

*

*

This class is useful for people new to Java since it allows them to write programs using * input without having to fully understand the read / parse / handle exceptions model of the * standard Java classes and in particular Scanner. So once exceptions and object * chaining are covered this class ought not to be used, it is definitely just an "early * stepping stone" utility class for initial learning.

* * @author Russel Winder * @version 2004-12-16 */ public class Input implements Closeable, Iterator { /** * A reference to the associated Scanner that supplies all the actual input * functionality. *

*

This is protected and not final rather than private and final (as we might have * expected it to be) so that FileInput can access the variable. This is * necessary because FileInput needs to capture all exceptions that can happen * during construction, which means that the super constructor call cannot be * used. This appears to be something of a misfeature of Java.

*/ protected Scanner scanner; /** * The default constructor of an Input that assumes System.in is to * be the InputStream used. */ public Input() { this(System.in); } /** * Constructor of an Input object given an InputStream object. */ public Input(final InputStream in) { scanner = new Scanner(in); } /** * A finalizer to ensure all files are closed if an Input object is garbage * collected. */ public void finalize() { close(); } /** * Close the file when finished with it. */ public void close() { scanner.close(); } /** * @return true if there is more input, false otherwise. */ public boolean hasNext() { boolean returnValue = false; try { returnValue = scanner.hasNext(); } catch (IllegalStateException e) { illegalStateExceptionHandler(); } return returnValue; } /** * @return the next token (sequence of characters terminated by a whitespace) in the input * stream. */ public String next() { String returnValue = null; try { returnValue = scanner.next(); } catch (NoSuchElementException nsee) { noSuchElementHandler(); } catch (IllegalStateException ise) { illegalStateExceptionHandler(); } return returnValue; } /** * This operation is required in order to conform to Iterator<String> but is * not supported. Normally an UnsupportedOperationException would be thrown to * indicate this situation but the whole point is not to throw exceptions so this is simply a * "do nothing" method. */ public void remove() { } /** * NB This method currently has a mis-feature in that it returns false incorrectly when there * is a single end-of-line left in the file. * * @return true if there is a char to input, false * otherwise. */ public boolean hasNextChar() { // Why doesn't this work, it used to. //boolean returnValue = false ; //try { returnValue = scanner.hasNext ( "(?s)." ) ; } //catch ( IllegalStateException e ) { illegalStateExceptionHandler ( ) ; } //return returnValue ; return hasNext(); } /** * @return the next char in the input stream. */ public char nextChar() { char returnValue = '\0'; try { returnValue = scanner.findWithinHorizon("(?s).", 1).charAt(0); } catch (IllegalArgumentException iae) { // This cannot happen as it is clear in the statement that the horizon is 1 which is > 0 and // this exception only happens for negative horizons. System.exit(1); } catch (IllegalStateException ise) { illegalStateExceptionHandler(); } return returnValue; } /** * @return true if there is an int to input, false * otherwise. */ public boolean hasNextInt() { boolean returnValue = false; try { returnValue = scanner.hasNextInt(); } catch (IllegalStateException e) { illegalStateExceptionHandler(); } return returnValue; } /** * @return the next int in the input stream assumed to be in the default radix * which is 10. */ public int nextInt() { int returnValue = 0; try { returnValue = scanner.nextInt(); } catch (InputMismatchException ime) { inputMismatchExceptionHandler("int"); } catch (NoSuchElementException nsee) { noSuchElementHandler(); } catch (IllegalStateException ise) { illegalStateExceptionHandler(); } return returnValue; } /** * @param radix the radix of the input. * @return the next int in the input stream using the radix * radix. */ public int nextInt(final int radix) { int returnValue = 0; try { returnValue = scanner.nextInt(radix); } catch (InputMismatchException ime) { inputMismatchExceptionHandler("int"); } catch (NoSuchElementException nsee) { noSuchElementHandler(); } catch (IllegalStateException ise) { illegalStateExceptionHandler(); } return returnValue; } /** * @return true if there is a long to input, false * otherwise. */ public boolean hasNextLong() { boolean returnValue = false; try { returnValue = scanner.hasNextLong(); } catch (IllegalStateException e) { illegalStateExceptionHandler(); } return returnValue; } /** * @return the next long in the input stream assumed to be in the default radix * which is 10. */ public long nextLong() { long returnValue = 0; try { returnValue = scanner.nextLong(); } catch (InputMismatchException ime) { inputMismatchExceptionHandler("long"); } catch (NoSuchElementException nsee) { noSuchElementHandler(); } catch (IllegalStateException ise) { illegalStateExceptionHandler(); } return returnValue; } /** * @param radix the radix of the input sequence. * @return the next long in the input stream using the radix * radix. */ public long nextLong(final int radix) { long returnValue = 0; try { returnValue = scanner.nextLong(radix); } catch (InputMismatchException ime) { inputMismatchExceptionHandler("long"); } catch (NoSuchElementException nsee) { noSuchElementHandler(); } catch (IllegalStateException ise) { illegalStateExceptionHandler(); } return returnValue; } /** * @return true if there is a BigInteger to input, false * otherwise. */ public boolean hasNextBigInteger() { boolean returnValue = false; try { returnValue = scanner.hasNextBigInteger(); } catch (IllegalStateException e) { illegalStateExceptionHandler(); } return returnValue; } /** * @return the next BigInteger in the input stream assumed to be in the default * radix which is 10. */ public BigInteger nextBigInteger() { BigInteger returnValue = new BigInteger("0"); try { returnValue = scanner.nextBigInteger(); } catch (InputMismatchException ime) { inputMismatchExceptionHandler("BigInteger"); } catch (NoSuchElementException nsee) { noSuchElementHandler(); } catch (IllegalStateException ise) { illegalStateExceptionHandler(); } return returnValue; } /** * @param radix the radix of the input sequence. * @return the next BigInteger in the input stream using the radix * radixtrue if there is a float to input, false * otherwise. */ public boolean hasNextFloat() { boolean returnValue = false; try { returnValue = scanner.hasNextFloat(); } catch (IllegalStateException e) { illegalStateExceptionHandler(); } return returnValue; } /** * @return the next float in the input stream. */ public float nextFloat() { float returnValue = 0; try { returnValue = scanner.nextFloat(); } catch (InputMismatchException ime) { inputMismatchExceptionHandler("float"); } catch (NoSuchElementException nsee) { noSuchElementHandler(); } catch (IllegalStateException ise) { illegalStateExceptionHandler(); } return returnValue; } /** * @return true if there is a double to input, false * otherwise. */ public boolean hasNextDouble() { boolean returnValue = false; try { returnValue = scanner.hasNextDouble(); } catch (IllegalStateException e) { illegalStateExceptionHandler(); } return returnValue; } /** * @return the next double in the input stream. */ public double nextDouble() { double returnValue = 0; try { returnValue = scanner.nextDouble(); } catch (InputMismatchException ime) { inputMismatchExceptionHandler("double"); } catch (NoSuchElementException nsee) { noSuchElementHandler(); } catch (IllegalStateException ise) { illegalStateExceptionHandler(); } return returnValue; } /** * @return true if there is a BigDecimal to input, * false otherwise. */ public boolean hasNextBigDecimal() { boolean returnValue = false; try { returnValue = scanner.hasNextBigDecimal(); } catch (IllegalStateException e) { illegalStateExceptionHandler(); } return returnValue; } /** * @return the next BigDecimal in the input stream. */ public BigDecimal nextBigDecimal() { BigDecimal returnValue = new BigDecimal("0"); try { returnValue = scanner.nextBigDecimal(); } catch (InputMismatchException ime) { inputMismatchExceptionHandler("BigDecimal"); } catch (NoSuchElementException nsee) { noSuchElementHandler(); } catch (IllegalStateException ise) { illegalStateExceptionHandler(); } return returnValue; } /** * @return true if there is more input including an end of line marker, * false otherwise. */ public boolean hasNextLine() { boolean returnValue = false; try { returnValue = scanner.hasNextLine(); } catch (IllegalStateException e) { illegalStateExceptionHandler(); } return returnValue; } /** * @return all the characters in the input stream up to and including the next end of line * marker in the input stream. */ public String nextLine() { String returnValue = null; try { returnValue = scanner.nextLine(); } catch (NoSuchElementException nsee) { noSuchElementHandler(); } catch (IllegalStateException ise) { illegalStateExceptionHandler(); } return returnValue; } /** * The method to handle an IllegalStateException. */ private void illegalStateExceptionHandler() { System.err.println("Input has been closed."); System.exit(1); } /** * The method to handle an InputMismatchException. */ private void inputMismatchExceptionHandler(final String type) { System.err.println("Input did not represent " + (type.equals("int") ? "an" : "a") + " " + type + " value."); System.exit(1); } /** * The method to handle an NoSuchElementException. */ private void noSuchElementHandler() { System.err.println("No input to be read."); System.exit(1); } }