Chapter: Java The Complete Reference - The Java Library - java.util : More Utility Classes

| Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail |

Scanner - java.util

Scanner is the complement of Formatter. It reads formatted input and converts it into its binary form.

Scanner

 

Scanner is the complement of Formatter. It reads formatted input and converts it into its binary form. Scanner can be used to read input from the console, a file, a string, or any source that implements the Readable interface or ReadableByteChannel. For example, you can use Scanner to read a number from the keyboard and assign its value to a variable. As you will see, given its power, Scanner is surprisingly easy to use.

 

The Scanner Constructors

 

Scanner defines the constructors shown in Table 19-15. In general, a Scanner can be created for a String, an InputStream, a File, or any object that implements the Readable or ReadableByteChannel interfaces. Here are some examples.

The following sequence creates a Scanner that reads the file Test.txt:

 

FileReader fin = new FileReader("Test.txt");

 

Scanner src = new Scanner(fin);

 

This works because FileReader implements the Readable interface. Thus, the call to the constructor resolves to Scanner(Readable).

This next line creates a Scanner that reads from standard input, which is the keyboard by default:

 

Scanner conin = new Scanner(System.in);

 

This works because System.in is an object of type InputStream. Thus, the call to the constructor maps to Scanner(InputStream).

The next sequence creates a Scanner that reads from a string.

 

String instr = "10 99.88 scanning is easy.";

 

Scanner conin = new Scanner(instr);

 

Scanning Basics

Once you have created a Scanner, it is a simple matter to use it to read formatted input. In general, a Scanner reads tokens from the underlying source that you specified when the Scanner was created. As it relates to Scanner, a token is a portion of input that is delineated


by a set of delimiters, which is whitespace by default. A token is read by matching it with a particular regular expression, which defines the format of the data. Although Scanner allows you to define the specific type of expression that its next input operation will match, it includes many predefined patterns, which match the primitive types, such as int and double, and strings. Thus, often you won’t need to specify a pattern to match.

 

In general, to use Scanner, follow this procedure:

 

         Determine if a specific type of input is available by calling one of Scanner’s hasNextX methods, where X is the type of data desired.

 

         If input is available, read it by calling one of Scanner’s nextX methods.

 

         Repeat the process until input is exhausted.

 

         Close the Scanner by calling close( ).

 

As the preceding indicates, Scanner defines two sets of methods that enable you to read input. The first are the hasNextX methods, which are shown in Table 19-16. These methods determine if the specified type of input is available. For example, calling hasNextInt( ) returns true only if the next token to be read is an integer. If the desired data is available, then you read it by calling one of Scanner’s nextX methods, which are shown in Table 19-17.

Method               Description

       

boolean hasNext( )       Returns true if another token of any type is available to be read. Returns false otherwise.

 

boolean hasNext(Pattern pattern)    Returns true if a token that matches the pattern passed in pattern is available to be read. Returns false otherwise.

       

boolean hasNext(String pattern)      Returns true if a token that matches the pattern passed in pattern is available to be read. Returns false otherwise.

       

boolean hasNextBigDecimal( )        Returns true if a value that can be stored in a BigDecimal object is available to be read. Returns false otherwise.

       

boolean hasNextBigInteger( ) Returns true if a value that can be stored in a BigInteger object is available to be read. Returns false otherwise. The default radix is used. (Unless changed, the default radix is 10.)

       

boolean hasNextBigInteger(int radix)        Returns true if a value in the specified radix that can be stored in a BigInteger object is available to be read. Returns false otherwise.

       

boolean hasNextBoolean( )    Returns true if a boolean value is available to be read. Returns false otherwise.

       

boolean hasNextByte( )          Returns true if a byte value is available to be read. Returns false otherwise. The default radix is used. (Unless changed, the default radix is 10.)

       

boolean hasNextByte(int radix)       Returns true if a byte value in the specified radix is available to be read. Returns false otherwise.

       

boolean hasNextDouble( )      Returns true if a double value is available to be read. Returns false otherwise.

       

boolean hasNextFloat( )         Returns true if a float value is available to be read. Returns false otherwise.

       

boolean hasNextInt( )   Returns true if an int value is available to be read. Returns false otherwise. The default radix is used. (Unless changed, the default radix is 10.)

       

boolean hasNextInt(int radix)          Returns true if an int value in the specified radix is available to be read. Returns false otherwise.

       

boolean hasNextLine( ) Returns true if a line of input is available. boolean hasNextLong( )        Returns true if a long value is available to be read. Returns false otherwise. The default radix is used. (Unless changed, the default radix is 10.)

       

boolean hasNextLong(int radix)      Returns true if a long value in the specified radix is available to be read. Returns false otherwise.

       

boolean hasNextShort( )        Returns true if a short value is available to be read.

                  Returns false otherwise. The default radix is used.

                  (Unless changed, the default radix is 10.)

       

boolean hasNextShort(int radix)     Returns true if a short value in the specified radix is available to be read. Returns false otherwise.

 

String next( )       Returns the next token of any type from the input source.    

       

String next(Pattern pattern)   Returns the next token that matches the pattern passed in pattern from the input source.

       

String next(String pattern)     Returns the next token that matches the pattern passed in pattern from the input source.

       

BigDecimal nextBigDecimal( )         Returns the next token as a BigDecimal object.

       

BigInteger nextBigInteger( )   Returns the next token as a BigInteger object. The default radix is used. (Unless changed, the default radix is 10.)       

       

BigInteger nextBigInteger(int radix) Returns the next token (using the specified radix) as a BigInteger object.

       

boolean nextBoolean( ) Returns the next token as a boolean value.

       

byte nextByte( )  Returns the next token as a byte value. The default radix is used. (Unless changed, the default radix is 10.)

       

byte nextByte(int radix)         Returns the next token (using the specified radix) as a byte value.        

       

double nextDouble( )    Returns the next token as a double value.

       

float nextFloat( ) Returns the next token as a float value.

       

int nextInt( )        Returns the next token as an int value. The default radix is used. (Unless changed, the default radix is 10.)

       

int nextInt(int radix)     Returns the next token (using the specified radix) as an int value.  

       

String nextLine( )          Returns the next line of input as a string.

       

long nextLong( )  Returns the next token as a long value. The default radix is used. (Unless changed, the default radix is 10.)

       

long nextLong(int radix)        Returns the next token (using the specified radix) as a long value.        

       

short nextShort( )         Returns the next token as a short value. The default radix is used. (Unless changed, the default radix is 10.)

       

short nextShort(int radix)      Returns the next token (using the specified radix) as a short value.


Table 19-17   The Scanner next Methods






For example, to read the next integer, call nextInt( ). The following sequence shows how to read a list of integers from the keyboard.

 

Scanner conin = new Scanner(System.in); int i;

 

// Read a list of integers.

while(conin.hasNextInt()) {

 

i = conin.nextInt(); // ...

}

 

The while loop stops as soon as the next token is not an integer. Thus, the loop stops reading integers as soon as a non-integer is encountered in the input stream.

If a next method cannot find the type of data it is looking for, it throws an

 

InputMismatchException. A NoSuchElementException is thrown if no more input is available. For this reason, it is best to first confirm that the desired type of data is available by calling a hasNext method before calling its corresponding next method.

 

Some Scanner Examples

 

Scanner makes what could be a tedious task into an easy one. To understand why, let’s look at some examples. The following program averages a list of numbers entered at the keyboard:

 

 

// Use Scanner to compute an average of the values.

import java.util.*;

 

class AvgNums {

 

public static void main(String args[]) {

Scanner conin = new Scanner(System.in);

 

int count = 0; double sum = 0.0;

 

System.out.println("Enter numbers to average.");

 

// Read and sum numbers.

while(conin.hasNext()) {

 

if(conin.hasNextDouble()) {

sum += conin.nextDouble(); count++;

}

 

else {

 

String str = conin.next();

if(str.equals("done")) break; else {

 

System.out.println("Data format error."); return;

 

}

 

}

 

}

 

conin.close();

 

System.out.println("Average is " + sum / count);

 

}

 

}

The program reads numbers from the keyboard, summing them in the process, until the user enters the string "done". It then stops input and displays the average of the numbers. Here is a sample run:

 

Enter numbers to average. 1.2 2 3.4 4

 

 

done

 

Average is 2.65

 

The program reads numbers until it encounters a token that does not represent a valid double value. When this occurs, it confirms that the token is the string "done". If it is, the program terminates normally. Otherwise, it displays an error.

 

Notice that the numbers are read by calling nextDouble( ). This method reads any number that can be converted into a double value, including an integer value, such as 2, and a floating-point value like 3.4. Thus, a number read by nextDouble( ) need not specify a decimal point. This same general principle applies to all next methods. They will match and read any data format that can represent the type of value being requested.

One thing that is especially nice about Scanner is that the same technique used to read from one source can be used to read from another. For example, here is the preceding program reworked to average a list of numbers contained in a text file:

 

// Use Scanner to compute an average of the values in a file.

import java.util.*;

 

import java.io.*;

 

class AvgFile {

 

public static void main(String args[]) throws IOException {

 

int count = 0; double sum = 0.0;

 

// Write output to a file.

 

FileWriter fout = new FileWriter("test.txt");

fout.write("2 3.4 5 6 7.4 9.1 10.5 done");

fout.close();

 

FileReader fin = new FileReader("Test.txt");

 

Scanner src = new Scanner(fin);

 

// Read and sum numbers.

while(src.hasNext()) {

 

if(src.hasNextDouble()) { sum += src.nextDouble(); count++;

}

 

String str = src.next(); if(str.equals("done")) break; else {

 

System.out.println("File format error."); return;

 

}

 

}

 

}

 

src.close();

 

System.out.println("Average is " + sum / count);

 

}

 

}

 

Here is the output:

 

Average is 6.2

 

The preceding program illustrates another important feature of Scanner. Notice that the file reader referred to by fin is not closed directly. Rather, it is closed automatically when src calls close( ). When you close a Scanner, the Readable associated with it is also closed (if that Readable implements the Closeable interface). Therefore, in this case, the file referred to by fin is automatically closed when src is closed.

Beginning with JDK 7, Scanner also implements the AutoCloseable interface. This means that it can be managed by a try-with-resources block. As explained in Chapter 13, when try-with-resources is used, the scanner is automatically closed when the block ends. For example, src in the preceding program could have been managed like this:

 

try (Scanner src = new Scanner(fin))

 

{

 

// Read and sum numbers.

while(src.hasNext()) {

 

if(src.hasNextDouble()) {

sum += src.nextDouble(); count++;

}

 

else {

 

String str = src.next();

if(str.equals("done")) break; else {

System.out.println("File format error."); return;

}

}

 

}

 

}

 

To clearly demonstrate the closing of a Scanner, the following examples will call close( ) explicitly. (Doing so also allows them to be compiled by versions of Java prior to JDK 7.) However, the try-with-resources approach is more streamlined and can help prevent errors. Its use is recommended for new code.

 

One other point: To keep this and the other examples in this section compact, I/O exceptions are simply thrown out of main( ). However, your real-world code will normally handle I/O exceptions itself.

 

You can use Scanner to read input that contains several different types of data—even if the order of that data is unknown in advance. You must simply check what type of data is available before reading it. For example, consider this program:

 

// Use Scanner to read various types of data from a file.

import java.util.*;

 

import java.io.*;

 

class ScanMixed {

 

public static void main(String args[]) throws IOException {

 

int i; double d; boolean b; String str;

 

// Write output to a file.

 

FileWriter fout = new FileWriter("test.txt");

fout.write("Testing Scanner 10 12.2 one true two false");

fout.close();

 

FileReader fin = new FileReader("Test.txt");

 

Scanner src = new Scanner(fin);

 

// Read to end.

while(src.hasNext()) {

 

if(src.hasNextInt()) { i = src.nextInt();

System.out.println("int: " + i);

 

}

 

else if(src.hasNextDouble()) { d = src.nextDouble();

 

System.out.println("double: " + d);

 

}

 

else if(src.hasNextBoolean()) { b = src.nextBoolean();

 

System.out.println("boolean: " + b);

 

}

 

else {

 

str = src.next(); System.out.println("String: " + str);

 

}

 

}

 

src.close();

 

}

 

Here is the output:

 

String: Testing String: Scanner int: 10

 

double: 12.2 String: one boolean: true String: two boolean: false

 

When reading mixed data types, as the preceding program does, you need to be a bit careful about the order in which you call the next methods. For example, if the loop reversed the order of the calls to nextInt( ) and nextDouble( ), both numeric values would have been read as doubles, because nextDouble( ) matches any numeric string that can be represented as a double.

 

Setting Delimiters

 

Scanner defines where a token starts and ends based on a set of delimiters. The default delimiters are the whitespace characters, and this is the delimiter set that the preceding examples have used. However, it is possible to change the delimiters by calling the useDelimiter( ) method, shown here:

 

Scanner useDelimiter(String pattern) Scanner useDelimiter(Pattern pattern)

 

Here, pattern is a regular expression that specifies the delimiter set.

 

Here is the program that reworks the average program shown earlier so that it reads a list of numbers that are separated by commas, and any number of spaces:

 

    //Use Scanner to compute an average a list of

 

    //comma-separated values.

 

import java.util.*; import java.io.*;

 

class SetDelimiters {

 

public static void main(String args[]) throws IOException {

 

int count = 0; double sum = 0.0;

 

// Write output to a file.

 

FileWriter fout = new FileWriter("test.txt");

 

// Now, store values in comma-separated

list. fout.write("2, 3.4, 5,6, 7.4, 9.1, 10.5, done"); fout.close();

 

FileReader fin = new FileReader("Test.txt");

 

Scanner src = new Scanner(fin);

    //Set delimiters to space and comma.

    src.useDelimiter(", *");

 

    //Read and sum numbers.

 

    while(src.hasNext()) {

 

if(src.hasNextDouble()) { sum += src.nextDouble(); count++;

}

 

else {

 

String str = src.next();

if(str.equals("done")) break; else {

 

System.out.println("File format error."); return;

 

}

 

}

 

}

 

src.close();

 

System.out.println("Average is " + sum / count);

 

}

 

}

 

In this version, the numbers written to test.txt are separated by commas and spaces. The use of the delimiter pattern ", * " tells Scanner to match a comma and zero or more spaces as delimiters. The output is the same as before.

You can obtain the current delimiter pattern by calling delimiter( ), shown here: Pattern delimiter( )

 

Other Scanner Features

Scanner defines several other methods in addition to those already discussed. One that is particularly useful in some circumstances is findInLine( ). Its general forms are shown here:

String findInLine(Pattern pattern)

String findInLine(String pattern)

This method searches for the specified pattern within the next line of text. If the pattern is found, the matching token is consumed and returned. Otherwise, null is returned. It operates independently of any delimiter set. This method is useful if you want to locate a specific pattern. For example, the following program locates the Age field in the input string and then displays the age:

 

 

// Demonstrate findInLine().

import java.util.*;

 

class FindInLineDemo {

public static void main(String args[]) { String instr = "Name: Tom Age: 28 ID: 77";

Scanner conin = new Scanner(instr);

 

// Find and display age.

conin.findInLine("Age:"); // find Age

 

if(conin.hasNext())

 

System.out.println(conin.next()); else

 

System.out.println("Error!");

 

conin.close();

 

}

 

}

 

The output is 28. In the program, findInLine( ) is used to find an occurrence of the pattern "Age". Once found, the next token is read, which is the age.

Related to findInLine( ) is findWithinHorizon( ). It is shown here:

 

String findWithinHorizon(Pattern pattern, int count)

 

String findWithinHorizon(String pattern, int count)

 

This method attempts to find an occurrence of the specified pattern within the next count characters. If successful, it returns the matching pattern. Otherwise, it returns null. If count is zero, then all input is searched until either a match is found or the end of input is encountered.

 

You can bypass a pattern using skip( ), shown here:

 

Scanner skip(Pattern pattern)

 

Scanner skip(String pattern)

 

If pattern is matched, skip( ) simply advances beyond it and returns a reference to the invoking object. If pattern is not found, skip( ) throws NoSuchElementException.

Other Scanner methods include radix( ), which returns the default radix used by the Scanner; useRadix( ), which sets the radix; reset( ), which resets the scanner; and close( ), which closes the scanner.

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail


Copyright © 2018-2020 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.