Java Cookbook, Second Edition
Problem
You have JDK 1.5 and you want the ease of use that the java.util.Scanner class brings to simple reading tasks. Solution
Use Scanner's next( ) methods for reading. Discussion
The Scanner class lets you read an input source by tokens, somewhat analogous to the StreamTokenizer described in Recipe 10.4. The Scanner is more flexible in some ways it lets you break tokens based on spaces or regular expressions but less in others you need to know the kind of token you are reading. This class bears some resemblance to the C-language scanf( ) function, but in the Scanner you specify the input token types by calling methods like nextInt( ), nextDouble( ), and so on. Here is a simple example of scanning: // From ScannerTest.java String sampleDate = "25 Dec 1988"; Scanner sDate = Scanner.create(sampleDate); int dom = sDate.nextInt( ); String mon = sDate.next( ); int year = sDate.nextInt( ); The Scanner recognizes Java's eight built-in types, as well as BigInteger and BigDecimal. It can also return input tokens as Strings or by matching regular expressions (see Chapter 4). Table 10-3 lists the "next" methods and corresponding "has" methods; the "has" method returns true if the corresponding "next" method would succeed. There is no nextString( ) method; just use next( ) to get the next token as a String.
The Scanner class does not provide any public constructors; you must call the static create( ) method with an input source, which can be a File object (Chapter 11), an InputStream, a String, or Readable (new in 1.5, Readable is an interface that Reader and all its subclasses implement). One way of using the Scanner is based on the Iterator pattern, using while (scanner.hasNext( )) to control the iteration. Example 10-4 shows the simple calculator from Recipe 10.4 rewritten[4] to use the Scanner class. [4] If this were code in a maintained project, I might factor out some of the common code among these two calculators, as well as the one in Recipe 5.19, and divide the code better using interfaces. However, this would detract from the simplicity of self-contained examples. Example 10-4. Simple calculator using java.util.Scanner
import java.io.*; import java.util.Scanner; import java.util.Stack; /** * SimpleCalc -- simple calculator using 1.5 java.util.Scanner * @version $Id: ch10.xml,v 1.5 2004/05/04 20:12:12 ian Exp $ */ public class SimpleCalcScanner { /** The Scanner */ protected Scanner scan; /** The output */ protected PrintWriter out = new PrintWriter(System.out); /** The variable name (not used in this version) */ protected String variable; /** The operand stack */ protected Stack s = new Stack( ); /* Driver - main program */ public static void main(String[] av) throws IOException { if (av.length == 0) new SimpleCalcScanner( new InputStreamReader(System.in)).doCalc( ); else for (int i=0; i<av.length; i++) new SimpleCalcScanner(av[i]).doCalc( ); } /** Construct a SimpleCalcScanner by name */ public SimpleCalcScanner(String fileName) throws IOException { this(new FileReader(fileName)); } /** Construct a SimpleCalcScanner from an open Reader */ public SimpleCalcScanner(Reader rdr) throws IOException { scan = new Scanner(rdr); // Control the input character set: scan.slashSlashComments(true); // treat "//" as comments scan.ordinaryChar('-'); // used for subtraction scan.ordinaryChar('/'); // used for division } /** Construct a SimpleCalcScanner from a Reader and a PrintWriter */ public SimpleCalcScanner(Reader rdr, PrintWriter pw) throws IOException { this(rdr); setWriter(pw); } /** Change the output to go to a new PrintWriter */ public void setWriter(PrintWriter pw) { out = pw; } protected void doCalc( ) throws IOException { int iType; double tmp; while (scan.hasNext( )) { if (scan.hasNextDouble( )) { push(scan.nextDouble( )); } else { String token = scan.next( ).toString( ); if (token.equals("+")) { // Found + operator, perform it immediately. push(pop( ) + pop( )); } else if (token.equals("-")) { // Found - operator, perform it (order matters). tmp = pop( ); push(pop( ) - tmp); } else if (token.equals("*")) { // Multiply is commutative push(pop( ) * pop( )); } else if (token.equals("/")) { // Handle division carefully: order matters! tmp = pop( ); push(pop( ) / tmp); } else if (token.equals("=")) { out.println(peek( )); } else { out.println("What's this? " + token); } } } } void push(double val) { s.push(new Double(val)); } double pop( ) { return ((Double)s.pop( )).doubleValue( ); } double peek( ) { return ((Double)s.peek( )).doubleValue( ); } void clearStack( ) { s.removeAllElements( ); } } |