La clase Scanner

Véase http://java.sun.com/j2se/1.5.0/docs/api/java/util/Scanner.html.

La clase Scanner provee un sencillo scanner que puede analizar tipos Java primitivos utilizando expresiones regulares.

Un scanner descompone su entrada en tokens utilizando un patrón delimitador, que por defecto es blancos. Los tokens resultantes pueden ser convertidos en diversos tipos de valores usando diversos métodos next.

next y hasNext

The next() and hasNext() methods and their primitive-type companion methods (such as nextInt() and hasNextInt()) first skip any input that matches the delimiter pattern, and then attempt to return the next token. Both hasNext and next methods may block waiting for further input. Whether a hasNext method blocks has no connection to whether or not its associated next method will block.

A scanner will default to interpreting numbers as decimal unless a different radix has been set by using the useRadix(int) method.

generaciondecodigos@nereida:~/src/groovy/strings$ cat -n UseScanner3.groovy
     1  #!/usr/bin/env groovy
     2  // On a Java 5 or 6 JVM, Groovy can also make use of Scanners:
     3  Scanner sc = new Scanner(new File("myNumbers"));
     4  sc.useDelimiter("\\D+")
     5  while (sc.hasNext()) {
     6    n = sc.next();
     7    println "One more $n"
     8  }
generaciondecodigos@nereida:~/src/groovy/strings$ cat -n myNumbers
     1  123
     2  ab 456
     3  78910
     4  45
generaciondecodigos@nereida:~/src/groovy/strings$ ./UseScanner3.groovy
One more 123
One more 456
One more 78910
One more 45

findInLine

The findInLine(java.lang.String), findWithinHorizon(java.lang.String, int), and skip(java.util.regex.Pattern) methods operate independently of the delimiter pattern. These methods will attempt to match the specified pattern with no regard to delimiters in the input and thus can be used in special circumstances where delimiters are not relevant. These methods may block waiting for more input.

Esto es lo que dice el manual sobre findInLine:

public String findInLine(Pattern pattern)

Attempts to find the next occurrence of the specified pattern ignoring delimiters. If the pattern is found before the next line separator, the scanner advances past the input that matched and returns the string that matched the pattern. If no such pattern is detected in the input up to the next line separator, then null is returned and the scanner's position is unchanged. This method may block waiting for input that matches the pattern.

Since this method continues to search through the input looking for the specified pattern, it may buffer all of the input searching for the desired token if no line separators are present.

Veamos un ejemplo:
generaciondecodigos@nereida:~/src/groovy/strings$ cat -n findInLine.groovy
     1  instr = "Name: Joe Age: 28 ID: 77";
     2
     3  Scanner conin = new Scanner(instr);
     4
     5  conin.findInLine("Age:"); // find Age
     6
     7  while (conin.hasNext()) {
     8    n = conin.next();
     9    println n
    10  }
generaciondecodigos@nereida:~/src/groovy/strings$ groovy findInLine.groovy
28
ID:
77
El siguiente ejemplo recoje el match en un objeto:
generaciondecodigos@nereida:~/src/groovy/strings$ cat -n UseScanner.groovy
     1  #!/usr/bin/env groovy
     2  // On a Java 5 or 6 JVM, Groovy can also make use of Scanners:
     3  data = 'hippopotamus means river horse'
     4  println data
     5
     6  s = new Scanner(data)
     7  s.findInLine(/(.{5}).{8}(.{5}) (.{5}) (.*)/)
     8  m = s.match()
     9  println m.groupCount()
    10
    11  fields = []
    12  (1..m.groupCount()).each{ fields << m.group(it) }
    13
    14  assert fields == ['hippo', 'means', 'river', 'horse']
    15  println fields
generaciondecodigos@nereida:~/src/groovy/strings$ ./UseScanner.groovy
hippopotamus means river horse
4
[hippo, means, river, horse]

Locales

An instance of this class is capable of scanning numbers in the standard formats as well as in the formats of the scanner's locale. A scanner's initial locale is the value returned by the Locale.getDefault() method; it may be changed via the useLocale(java.util.Locale) method.

The localized formats are defined in terms of the following parameters, which for a particular locale are taken from that locale's DecimalFormat object, df, and its and DecimalFormatSymbols object, dfs.

    LocalGroupSeparator         The character used to separate thousands groups, i.e., dfs.getGroupingSeparator()
    LocalDecimalSeparator       The character used for the decimal point, i.e., dfs.getDecimalSeparator()
    LocalPositivePrefix         The string that appears before a positive number (may be empty), i.e., df.getPositivePrefix()
    LocalPositiveSuffix         The string that appears after a positive number (may be empty), i.e., df.getPositiveSuffix()
    LocalNegativePrefix         The string that appears before a negative number (may be empty), i.e., df.getNegativePrefix()
    LocalNegativeSuffix         The string that appears after a negative number (may be empty), i.e., df.getNegativeSuffix()
    LocalNaN    The string that represents not-a-number for floating-point values, i.e., dfs.getInfinity()
    LocalInfinity       The string that represents infinity for floating-point values, i.e., dfs.getInfinity()

The strings that can be parsed as numbers by an instance of this class are specified in terms of the following regular-expression grammar, where Rmax is the highest digit in the radix being used (for example, Rmax is 9 in base 10).

El siguiente ejemplo lee números en formato español de un fichero y los suma:

generaciondecodigos@nereida:~/src/groovy/strings$ cat -n ScanSum.groovy
     1  Scanner s = null;
     2  sum = 0.0;
     3  s = new Scanner(new File("esnumbers.txt"));
     4  s.useLocale(Locale.FRANCE);
     5
     6  while (s.hasNext()) {
     7    if (s.hasNextDouble()) {
     8            next = s.nextDouble();
     9            sum += next;
    10            println "next = $next sum=$sum"
    11    } else {
    12        s.next();
    13    }
    14  }
    15  s.close();
    16
    17  System.out.println(sum);
generaciondecodigos@nereida:~/src/groovy/strings$ cat -n esnumbers.txt
     1  3,5
     2  4,2
     3  83
generaciondecodigos@nereida:~/src/groovy/strings$ groovy ScanSum.groovy
next = 3.5 sum=3.5
next = 4.2 sum=7.7
next = 83.0 sum=90.7
90.7



Subsecciones
Casiano Rodríguez León
2010-04-30