Scanner.java revision 49965c1dc9da104344f4893a05e45795a5740d20
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27package java.util; 28 29import java.nio.file.Path; 30import java.nio.file.Files; 31import java.util.regex.*; 32import java.io.*; 33import java.math.*; 34import java.nio.*; 35import java.nio.channels.*; 36import java.nio.charset.*; 37import java.text.*; 38import java.util.Locale; 39 40import sun.misc.LRUCache; 41 42/** 43 * A simple text scanner which can parse primitive types and strings using 44 * regular expressions. 45 * 46 * <p>A <code>Scanner</code> breaks its input into tokens using a 47 * delimiter pattern, which by default matches whitespace. The resulting 48 * tokens may then be converted into values of different types using the 49 * various <tt>next</tt> methods. 50 * 51 * <p>For example, this code allows a user to read a number from 52 * <tt>System.in</tt>: 53 * <blockquote><pre> 54 * Scanner sc = new Scanner(System.in); 55 * int i = sc.nextInt(); 56 * </pre></blockquote> 57 * 58 * <p>As another example, this code allows <code>long</code> types to be 59 * assigned from entries in a file <code>myNumbers</code>: 60 * <blockquote><pre> 61 * Scanner sc = new Scanner(new File("myNumbers")); 62 * while (sc.hasNextLong()) { 63 * long aLong = sc.nextLong(); 64 * }</pre></blockquote> 65 * 66 * <p>The scanner can also use delimiters other than whitespace. This 67 * example reads several items in from a string: 68 *<blockquote><pre> 69 * String input = "1 fish 2 fish red fish blue fish"; 70 * Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*"); 71 * System.out.println(s.nextInt()); 72 * System.out.println(s.nextInt()); 73 * System.out.println(s.next()); 74 * System.out.println(s.next()); 75 * s.close(); </pre></blockquote> 76 * <p> 77 * prints the following output: 78 * <blockquote><pre> 79 * 1 80 * 2 81 * red 82 * blue </pre></blockquote> 83 * 84 * <p>The same output can be generated with this code, which uses a regular 85 * expression to parse all four tokens at once: 86 *<blockquote><pre> 87 * String input = "1 fish 2 fish red fish blue fish"; 88 * Scanner s = new Scanner(input); 89 * s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)"); 90 * MatchResult result = s.match(); 91 * for (int i=1; i<=result.groupCount(); i++) 92 * System.out.println(result.group(i)); 93 * s.close(); </pre></blockquote> 94 * 95 * <p>The <a name="default-delimiter">default whitespace delimiter</a> used 96 * by a scanner is as recognized by {@link java.lang.Character}.{@link 97 * java.lang.Character#isWhitespace(char) isWhitespace}. The {@link #reset} 98 * method will reset the value of the scanner's delimiter to the default 99 * whitespace delimiter regardless of whether it was previously changed. 100 * 101 * <p>A scanning operation may block waiting for input. 102 * 103 * <p>The {@link #next} and {@link #hasNext} methods and their 104 * primitive-type companion methods (such as {@link #nextInt} and 105 * {@link #hasNextInt}) first skip any input that matches the delimiter 106 * pattern, and then attempt to return the next token. Both <tt>hasNext</tt> 107 * and <tt>next</tt> methods may block waiting for further input. Whether a 108 * <tt>hasNext</tt> method blocks has no connection to whether or not its 109 * associated <tt>next</tt> method will block. 110 * 111 * <p> The {@link #findInLine}, {@link #findWithinHorizon}, and {@link #skip} 112 * methods operate independently of the delimiter pattern. These methods will 113 * attempt to match the specified pattern with no regard to delimiters in the 114 * input and thus can be used in special circumstances where delimiters are 115 * not relevant. These methods may block waiting for more input. 116 * 117 * <p>When a scanner throws an {@link InputMismatchException}, the scanner 118 * will not pass the token that caused the exception, so that it may be 119 * retrieved or skipped via some other method. 120 * 121 * <p>Depending upon the type of delimiting pattern, empty tokens may be 122 * returned. For example, the pattern <tt>"\\s+"</tt> will return no empty 123 * tokens since it matches multiple instances of the delimiter. The delimiting 124 * pattern <tt>"\\s"</tt> could return empty tokens since it only passes one 125 * space at a time. 126 * 127 * <p> A scanner can read text from any object which implements the {@link 128 * java.lang.Readable} interface. If an invocation of the underlying 129 * readable's {@link java.lang.Readable#read} method throws an {@link 130 * java.io.IOException} then the scanner assumes that the end of the input 131 * has been reached. The most recent <tt>IOException</tt> thrown by the 132 * underlying readable can be retrieved via the {@link #ioException} method. 133 * 134 * <p>When a <code>Scanner</code> is closed, it will close its input source 135 * if the source implements the {@link java.io.Closeable} interface. 136 * 137 * <p>A <code>Scanner</code> is not safe for multithreaded use without 138 * external synchronization. 139 * 140 * <p>Unless otherwise mentioned, passing a <code>null</code> parameter into 141 * any method of a <code>Scanner</code> will cause a 142 * <code>NullPointerException</code> to be thrown. 143 * 144 * <p>A scanner will default to interpreting numbers as decimal unless a 145 * different radix has been set by using the {@link #useRadix} method. The 146 * {@link #reset} method will reset the value of the scanner's radix to 147 * <code>10</code> regardless of whether it was previously changed. 148 * 149 * <a name="localized-numbers"> 150 * <h4> Localized numbers </h4> 151 * 152 * <p> An instance of this class is capable of scanning numbers in the standard 153 * formats as well as in the formats of the scanner's locale. A scanner's 154 * <a name="initial-locale">initial locale </a>is the value returned by the {@link 155 * java.util.Locale#getDefault} method; it may be changed via the {@link 156 * #useLocale} method. The {@link #reset} method will reset the value of the 157 * scanner's locale to the initial locale regardless of whether it was 158 * previously changed. 159 * 160 * <p>The localized formats are defined in terms of the following parameters, 161 * which for a particular locale are taken from that locale's {@link 162 * java.text.DecimalFormat DecimalFormat} object, <tt>df</tt>, and its and 163 * {@link java.text.DecimalFormatSymbols DecimalFormatSymbols} object, 164 * <tt>dfs</tt>. 165 * 166 * <blockquote><table> 167 * <tr><td valign="top"><i>LocalGroupSeparator </i></td> 168 * <td valign="top">The character used to separate thousands groups, 169 * <i>i.e.,</i> <tt>dfs.</tt>{@link 170 * java.text.DecimalFormatSymbols#getGroupingSeparator 171 * getGroupingSeparator()}</td></tr> 172 * <tr><td valign="top"><i>LocalDecimalSeparator </i></td> 173 * <td valign="top">The character used for the decimal point, 174 * <i>i.e.,</i> <tt>dfs.</tt>{@link 175 * java.text.DecimalFormatSymbols#getDecimalSeparator 176 * getDecimalSeparator()}</td></tr> 177 * <tr><td valign="top"><i>LocalPositivePrefix </i></td> 178 * <td valign="top">The string that appears before a positive number (may 179 * be empty), <i>i.e.,</i> <tt>df.</tt>{@link 180 * java.text.DecimalFormat#getPositivePrefix 181 * getPositivePrefix()}</td></tr> 182 * <tr><td valign="top"><i>LocalPositiveSuffix </i></td> 183 * <td valign="top">The string that appears after a positive number (may be 184 * empty), <i>i.e.,</i> <tt>df.</tt>{@link 185 * java.text.DecimalFormat#getPositiveSuffix 186 * getPositiveSuffix()}</td></tr> 187 * <tr><td valign="top"><i>LocalNegativePrefix </i></td> 188 * <td valign="top">The string that appears before a negative number (may 189 * be empty), <i>i.e.,</i> <tt>df.</tt>{@link 190 * java.text.DecimalFormat#getNegativePrefix 191 * getNegativePrefix()}</td></tr> 192 * <tr><td valign="top"><i>LocalNegativeSuffix </i></td> 193 * <td valign="top">The string that appears after a negative number (may be 194 * empty), <i>i.e.,</i> <tt>df.</tt>{@link 195 * java.text.DecimalFormat#getNegativeSuffix 196 * getNegativeSuffix()}</td></tr> 197 * <tr><td valign="top"><i>LocalNaN </i></td> 198 * <td valign="top">The string that represents not-a-number for 199 * floating-point values, 200 * <i>i.e.,</i> <tt>dfs.</tt>{@link 201 * java.text.DecimalFormatSymbols#getNaN 202 * getNaN()}</td></tr> 203 * <tr><td valign="top"><i>LocalInfinity </i></td> 204 * <td valign="top">The string that represents infinity for floating-point 205 * values, <i>i.e.,</i> <tt>dfs.</tt>{@link 206 * java.text.DecimalFormatSymbols#getInfinity 207 * getInfinity()}</td></tr> 208 * </table></blockquote> 209 * 210 * <a name="number-syntax"> 211 * <h4> Number syntax </h4> 212 * 213 * <p> The strings that can be parsed as numbers by an instance of this class 214 * are specified in terms of the following regular-expression grammar, where 215 * Rmax is the highest digit in the radix being used (for example, Rmax is 9 216 * in base 10). 217 * 218 * <p> 219 * <table cellspacing=0 cellpadding=0 align=center> 220 * 221 * <tr><td valign=top align=right><i>NonASCIIDigit</i> ::</td> 222 * <td valign=top>= A non-ASCII character c for which 223 * {@link java.lang.Character#isDigit Character.isDigit}<tt>(c)</tt> 224 * returns true</td></tr> 225 * 226 * <tr><td> </td></tr> 227 * 228 * <tr><td align=right><i>Non0Digit</i> ::</td> 229 * <td><tt>= [1-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i></td></tr> 230 * 231 * <tr><td> </td></tr> 232 * 233 * <tr><td align=right><i>Digit</i> ::</td> 234 * <td><tt>= [0-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i></td></tr> 235 * 236 * <tr><td> </td></tr> 237 * 238 * <tr><td valign=top align=right><i>GroupedNumeral</i> ::</td> 239 * <td valign=top> 240 * <table cellpadding=0 cellspacing=0> 241 * <tr><td><tt>= ( </tt></td> 242 * <td><i>Non0Digit</i><tt> 243 * </tt><i>Digit</i><tt>? 244 * </tt><i>Digit</i><tt>?</tt></td></tr> 245 * <tr><td></td> 246 * <td><tt>( </tt><i>LocalGroupSeparator</i><tt> 247 * </tt><i>Digit</i><tt> 248 * </tt><i>Digit</i><tt> 249 * </tt><i>Digit</i><tt> )+ )</tt></td></tr> 250 * </table></td></tr> 251 * 252 * <tr><td> </td></tr> 253 * 254 * <tr><td align=right><i>Numeral</i> ::</td> 255 * <td><tt>= ( ( </tt><i>Digit</i><tt>+ ) 256 * | </tt><i>GroupedNumeral</i><tt> )</tt></td></tr> 257 * 258 * <tr><td> </td></tr> 259 * 260 * <tr><td valign=top align=right> 261 * <a name="Integer-regex"><i>Integer</i> ::</td> 262 * <td valign=top><tt>= ( [-+]? ( </tt><i>Numeral</i><tt> 263 * ) )</tt></td></tr> 264 * <tr><td></td> 265 * <td><tt>| </tt><i>LocalPositivePrefix</i><tt> </tt><i>Numeral</i><tt> 266 * </tt><i>LocalPositiveSuffix</i></td></tr> 267 * <tr><td></td> 268 * <td><tt>| </tt><i>LocalNegativePrefix</i><tt> </tt><i>Numeral</i><tt> 269 * </tt><i>LocalNegativeSuffix</i></td></tr> 270 * 271 * <tr><td> </td></tr> 272 * 273 * <tr><td align=right><i>DecimalNumeral</i> ::</td> 274 * <td><tt>= </tt><i>Numeral</i></td></tr> 275 * <tr><td></td> 276 * <td><tt>| </tt><i>Numeral</i><tt> 277 * </tt><i>LocalDecimalSeparator</i><tt> 278 * </tt><i>Digit</i><tt>*</tt></td></tr> 279 * <tr><td></td> 280 * <td><tt>| </tt><i>LocalDecimalSeparator</i><tt> 281 * </tt><i>Digit</i><tt>+</tt></td></tr> 282 * 283 * <tr><td> </td></tr> 284 * 285 * <tr><td align=right><i>Exponent</i> ::</td> 286 * <td><tt>= ( [eE] [+-]? </tt><i>Digit</i><tt>+ )</tt></td></tr> 287 * 288 * <tr><td> </td></tr> 289 * 290 * <tr><td align=right> 291 * <a name="Decimal-regex"><i>Decimal</i> ::</td> 292 * <td><tt>= ( [-+]? </tt><i>DecimalNumeral</i><tt> 293 * </tt><i>Exponent</i><tt>? )</tt></td></tr> 294 * <tr><td></td> 295 * <td><tt>| </tt><i>LocalPositivePrefix</i><tt> 296 * </tt><i>DecimalNumeral</i><tt> 297 * </tt><i>LocalPositiveSuffix</i> 298 * </tt><i>Exponent</i><tt>?</td></tr> 299 * <tr><td></td> 300 * <td><tt>| </tt><i>LocalNegativePrefix</i><tt> 301 * </tt><i>DecimalNumeral</i><tt> 302 * </tt><i>LocalNegativeSuffix</i> 303 * </tt><i>Exponent</i><tt>?</td></tr> 304 * 305 * <tr><td> </td></tr> 306 * 307 * <tr><td align=right><i>HexFloat</i> ::</td> 308 * <td><tt>= [-+]? 0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+ 309 * ([pP][-+]?[0-9]+)?</tt></td></tr> 310 * 311 * <tr><td> </td></tr> 312 * 313 * <tr><td align=right><i>NonNumber</i> ::</td> 314 * <td valign=top><tt>= NaN 315 * | </tt><i>LocalNan</i><tt> 316 * | Infinity 317 * | </tt><i>LocalInfinity</i></td></tr> 318 * 319 * <tr><td> </td></tr> 320 * 321 * <tr><td align=right><i>SignedNonNumber</i> ::</td> 322 * <td><tt>= ( [-+]? </tt><i>NonNumber</i><tt> )</tt></td></tr> 323 * <tr><td></td> 324 * <td><tt>| </tt><i>LocalPositivePrefix</i><tt> 325 * </tt><i>NonNumber</i><tt> 326 * </tt><i>LocalPositiveSuffix</i></td></tr> 327 * <tr><td></td> 328 * <td><tt>| </tt><i>LocalNegativePrefix</i><tt> 329 * </tt><i>NonNumber</i><tt> 330 * </tt><i>LocalNegativeSuffix</i></td></tr> 331 * 332 * <tr><td> </td></tr> 333 * 334 * <tr><td valign=top align=right> 335 * <a name="Float-regex"><i>Float</i> ::</td> 336 * <td valign=top><tt>= </tt><i>Decimal</i><tt></td></tr> 337 * <tr><td></td> 338 * <td><tt>| </tt><i>HexFloat</i><tt></td></tr> 339 * <tr><td></td> 340 * <td><tt>| </tt><i>SignedNonNumber</i><tt></td></tr> 341 * 342 * </table> 343 * </center> 344 * 345 * <p> Whitespace is not significant in the above regular expressions. 346 * 347 * @since 1.5 348 */ 349public final class Scanner implements Iterator<String>, Closeable { 350 351 // Internal buffer used to hold input 352 private CharBuffer buf; 353 354 // Size of internal character buffer 355 private static final int BUFFER_SIZE = 1024; // change to 1024; 356 357 // The index into the buffer currently held by the Scanner 358 private int position; 359 360 // Internal matcher used for finding delimiters 361 private Matcher matcher; 362 363 // Pattern used to delimit tokens 364 private Pattern delimPattern; 365 366 // Pattern found in last hasNext operation 367 private Pattern hasNextPattern; 368 369 // Position after last hasNext operation 370 private int hasNextPosition; 371 372 // Result after last hasNext operation 373 private String hasNextResult; 374 375 // The input source 376 private Readable source; 377 378 // Boolean is true if source is done 379 private boolean sourceClosed = false; 380 381 // Boolean indicating more input is required 382 private boolean needInput = false; 383 384 // Boolean indicating if a delim has been skipped this operation 385 private boolean skipped = false; 386 387 // A store of a position that the scanner may fall back to 388 private int savedScannerPosition = -1; 389 390 // A cache of the last primitive type scanned 391 private Object typeCache = null; 392 393 // Boolean indicating if a match result is available 394 private boolean matchValid = false; 395 396 // Boolean indicating if this scanner has been closed 397 private boolean closed = false; 398 399 // The current radix used by this scanner 400 private int radix = 10; 401 402 // The default radix for this scanner 403 private int defaultRadix = 10; 404 405 // The locale used by this scanner 406 private Locale locale = null; 407 408 // A cache of the last few recently used Patterns 409 private LRUCache<String,Pattern> patternCache = 410 new LRUCache<String,Pattern>(7) { 411 protected Pattern create(String s) { 412 return Pattern.compile(s); 413 } 414 protected boolean hasName(Pattern p, String s) { 415 return p.pattern().equals(s); 416 } 417 }; 418 419 // A holder of the last IOException encountered 420 private IOException lastException; 421 422 // A pattern for java whitespace 423 private static Pattern WHITESPACE_PATTERN = Pattern.compile( 424 "\\p{javaWhitespace}+"); 425 426 // A pattern for any token 427 private static Pattern FIND_ANY_PATTERN = Pattern.compile("(?s).*"); 428 429 // A pattern for non-ASCII digits 430 private static Pattern NON_ASCII_DIGIT = Pattern.compile( 431 "[\\p{javaDigit}&&[^0-9]]"); 432 433 // Fields and methods to support scanning primitive types 434 435 /** 436 * Locale dependent values used to scan numbers 437 */ 438 private String groupSeparator = "\\,"; 439 private String decimalSeparator = "\\."; 440 private String nanString = "NaN"; 441 private String infinityString = "Infinity"; 442 private String positivePrefix = ""; 443 private String negativePrefix = "\\-"; 444 private String positiveSuffix = ""; 445 private String negativeSuffix = ""; 446 447 /** 448 * Fields and an accessor method to match booleans 449 */ 450 private static volatile Pattern boolPattern; 451 private static final String BOOLEAN_PATTERN = "true|false"; 452 private static Pattern boolPattern() { 453 Pattern bp = boolPattern; 454 if (bp == null) 455 boolPattern = bp = Pattern.compile(BOOLEAN_PATTERN, 456 Pattern.CASE_INSENSITIVE); 457 return bp; 458 } 459 460 /** 461 * Fields and methods to match bytes, shorts, ints, and longs 462 */ 463 private Pattern integerPattern; 464 private String digits = "0123456789abcdefghijklmnopqrstuvwxyz"; 465 private String non0Digit = "[\\p{javaDigit}&&[^0]]"; 466 private int SIMPLE_GROUP_INDEX = 5; 467 private String buildIntegerPatternString() { 468 String radixDigits = digits.substring(0, radix); 469 // Android changed : Support non-decimal starting digits. (i.e, a-z are valid radix digits). 470 String nonZeroRadixDigits = "((?i)[" + digits.substring(1, radix) + "]|(" + non0Digit + "))"; 471 472 // \\p{javaDigit} is not guaranteed to be appropriate 473 // here but what can we do? The final authority will be 474 // whatever parse method is invoked, so ultimately the 475 // Scanner will do the right thing 476 String digit = "((?i)["+radixDigits+"]|\\p{javaDigit})"; 477 // Android changed : Support non-decimal starting digits. 478 String groupedNumeral = "("+nonZeroRadixDigits+digit+"?"+digit+"?("+ 479 groupSeparator+digit+digit+digit+")+)"; 480 // digit++ is the possessive form which is necessary for reducing 481 // backtracking that would otherwise cause unacceptable performance 482 String numeral = "(("+ digit+"++)|"+groupedNumeral+")"; 483 String javaStyleInteger = "([-+]?(" + numeral + "))"; 484 String negativeInteger = negativePrefix + numeral + negativeSuffix; 485 String positiveInteger = positivePrefix + numeral + positiveSuffix; 486 return "("+ javaStyleInteger + ")|(" + 487 positiveInteger + ")|(" + 488 negativeInteger + ")"; 489 } 490 private Pattern integerPattern() { 491 if (integerPattern == null) { 492 integerPattern = patternCache.forName(buildIntegerPatternString()); 493 } 494 return integerPattern; 495 } 496 497 /** 498 * Fields and an accessor method to match line separators 499 */ 500 private static volatile Pattern separatorPattern; 501 private static volatile Pattern linePattern; 502 private static final String LINE_SEPARATOR_PATTERN = 503 "\r\n|[\n\r\u2028\u2029\u0085]"; 504 private static final String LINE_PATTERN = ".*("+LINE_SEPARATOR_PATTERN+")|.+$"; 505 506 private static Pattern separatorPattern() { 507 Pattern sp = separatorPattern; 508 if (sp == null) 509 separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN); 510 return sp; 511 } 512 513 private static Pattern linePattern() { 514 Pattern lp = linePattern; 515 if (lp == null) 516 linePattern = lp = Pattern.compile(LINE_PATTERN); 517 return lp; 518 } 519 520 /** 521 * Fields and methods to match floats and doubles 522 */ 523 private Pattern floatPattern; 524 private Pattern decimalPattern; 525 private void buildFloatAndDecimalPattern() { 526 // \\p{javaDigit} may not be perfect, see above 527 String digit = "([0-9]|(\\p{javaDigit}))"; 528 String exponent = "([eE][+-]?"+digit+"+)?"; 529 String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+ 530 groupSeparator+digit+digit+digit+")+)"; 531 // Once again digit++ is used for performance, as above 532 String numeral = "(("+digit+"++)|"+groupedNumeral+")"; 533 String decimalNumeral = "("+numeral+"|"+numeral + 534 decimalSeparator + digit + "*+|"+ decimalSeparator + 535 digit + "++)"; 536 String nonNumber = "(NaN|"+nanString+"|Infinity|"+ 537 infinityString+")"; 538 String positiveFloat = "(" + positivePrefix + decimalNumeral + 539 positiveSuffix + exponent + ")"; 540 String negativeFloat = "(" + negativePrefix + decimalNumeral + 541 negativeSuffix + exponent + ")"; 542 String decimal = "(([-+]?" + decimalNumeral + exponent + ")|"+ 543 positiveFloat + "|" + negativeFloat + ")"; 544 String hexFloat = 545 "[-+]?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP][-+]?[0-9]+)?"; 546 String positiveNonNumber = "(" + positivePrefix + nonNumber + 547 positiveSuffix + ")"; 548 String negativeNonNumber = "(" + negativePrefix + nonNumber + 549 negativeSuffix + ")"; 550 String signedNonNumber = "(([-+]?"+nonNumber+")|" + 551 positiveNonNumber + "|" + 552 negativeNonNumber + ")"; 553 floatPattern = Pattern.compile(decimal + "|" + hexFloat + "|" + 554 signedNonNumber); 555 decimalPattern = Pattern.compile(decimal); 556 } 557 private Pattern floatPattern() { 558 if (floatPattern == null) { 559 buildFloatAndDecimalPattern(); 560 } 561 return floatPattern; 562 } 563 private Pattern decimalPattern() { 564 if (decimalPattern == null) { 565 buildFloatAndDecimalPattern(); 566 } 567 return decimalPattern; 568 } 569 570 // Constructors 571 572 /** 573 * Constructs a <code>Scanner</code> that returns values scanned 574 * from the specified source delimited by the specified pattern. 575 * 576 * @param source A character source implementing the Readable interface 577 * @param pattern A delimiting pattern 578 * @return A scanner with the specified source and pattern 579 */ 580 private Scanner(Readable source, Pattern pattern) { 581 assert source != null : "source should not be null"; 582 assert pattern != null : "pattern should not be null"; 583 this.source = source; 584 delimPattern = pattern; 585 buf = CharBuffer.allocate(BUFFER_SIZE); 586 buf.limit(0); 587 matcher = delimPattern.matcher(buf); 588 matcher.useTransparentBounds(true); 589 matcher.useAnchoringBounds(false); 590 useLocale(Locale.getDefault(Locale.Category.FORMAT)); 591 } 592 593 /** 594 * Constructs a new <code>Scanner</code> that produces values scanned 595 * from the specified source. 596 * 597 * @param source A character source implementing the {@link Readable} 598 * interface 599 */ 600 public Scanner(Readable source) { 601 this(Objects.requireNonNull(source, "source"), WHITESPACE_PATTERN); 602 } 603 604 /** 605 * Constructs a new <code>Scanner</code> that produces values scanned 606 * from the specified input stream. Bytes from the stream are converted 607 * into characters using the underlying platform's 608 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}. 609 * 610 * @param source An input stream to be scanned 611 */ 612 public Scanner(InputStream source) { 613 this(new InputStreamReader(source), WHITESPACE_PATTERN); 614 } 615 616 /** 617 * Constructs a new <code>Scanner</code> that produces values scanned 618 * from the specified input stream. Bytes from the stream are converted 619 * into characters using the specified charset. 620 * 621 * @param source An input stream to be scanned 622 * @param charsetName The encoding type used to convert bytes from the 623 * stream into characters to be scanned 624 * @throws IllegalArgumentException if the specified character set 625 * does not exist 626 */ 627 public Scanner(InputStream source, String charsetName) { 628 this(makeReadable(Objects.requireNonNull(source, "source"), toCharset(charsetName)), 629 WHITESPACE_PATTERN); 630 } 631 632 /** 633 * Returns a charset object for the given charset name. 634 * @throws NullPointerException is csn is null 635 * @throws IllegalArgumentException if the charset is not supported 636 */ 637 private static Charset toCharset(String csn) { 638 Objects.requireNonNull(csn, "charsetName"); 639 try { 640 return Charset.forName(csn); 641 } catch (IllegalCharsetNameException|UnsupportedCharsetException e) { 642 // IllegalArgumentException should be thrown 643 throw new IllegalArgumentException(e); 644 } 645 } 646 647 private static Readable makeReadable(InputStream source, Charset charset) { 648 return new InputStreamReader(source, charset); 649 } 650 651 /** 652 * Constructs a new <code>Scanner</code> that produces values scanned 653 * from the specified file. Bytes from the file are converted into 654 * characters using the underlying platform's 655 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}. 656 * 657 * @param source A file to be scanned 658 * @throws FileNotFoundException if source is not found 659 */ 660 public Scanner(File source) throws FileNotFoundException { 661 this((ReadableByteChannel)(new FileInputStream(source).getChannel())); 662 } 663 664 /** 665 * Constructs a new <code>Scanner</code> that produces values scanned 666 * from the specified file. Bytes from the file are converted into 667 * characters using the specified charset. 668 * 669 * @param source A file to be scanned 670 * @param charsetName The encoding type used to convert bytes from the file 671 * into characters to be scanned 672 * @throws FileNotFoundException if source is not found 673 * @throws IllegalArgumentException if the specified encoding is 674 * not found 675 */ 676 public Scanner(File source, String charsetName) 677 throws FileNotFoundException 678 { 679 this(Objects.requireNonNull(source), toDecoder(charsetName)); 680 } 681 682 private Scanner(File source, CharsetDecoder dec) 683 throws FileNotFoundException 684 { 685 this(makeReadable((ReadableByteChannel)(new FileInputStream(source).getChannel()), dec)); 686 } 687 688 private static CharsetDecoder toDecoder(String charsetName) { 689 // Android-changed: Throw an IAE instead of an NPE. 690 // Objects.requireNonNull(charsetName, "charsetName"); 691 if (charsetName == null) { 692 throw new IllegalArgumentException("charsetName == null"); 693 } 694 try { 695 return Charset.forName(charsetName).newDecoder(); 696 } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { 697 throw new IllegalArgumentException(charsetName); 698 } 699 } 700 701 private static Readable makeReadable(ReadableByteChannel source, 702 CharsetDecoder dec) { 703 return Channels.newReader(source, dec, -1); 704 } 705 706 /** 707 * Constructs a new <code>Scanner</code> that produces values scanned 708 * from the specified file. Bytes from the file are converted into 709 * characters using the underlying platform's 710 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}. 711 * 712 * @param source 713 * the path to the file to be scanned 714 * @throws IOException 715 * if an I/O error occurs opening source 716 * 717 * @since 1.7 718 */ 719 public Scanner(Path source) 720 throws IOException 721 { 722 this(Files.newInputStream(source)); 723 } 724 725 /** 726 * Constructs a new <code>Scanner</code> that produces values scanned 727 * from the specified file. Bytes from the file are converted into 728 * characters using the specified charset. 729 * 730 * @param source 731 * the path to the file to be scanned 732 * @param charsetName 733 * The encoding type used to convert bytes from the file 734 * into characters to be scanned 735 * @throws IOException 736 * if an I/O error occurs opening source 737 * @throws IllegalArgumentException 738 * if the specified encoding is not found 739 * @since 1.7 740 */ 741 public Scanner(Path source, String charsetName) throws IOException { 742 this(Objects.requireNonNull(source), toCharset(charsetName)); 743 } 744 745 private Scanner(Path source, Charset charset) throws IOException { 746 this(makeReadable(Files.newInputStream(source), charset)); 747 } 748 749 /** 750 * Constructs a new <code>Scanner</code> that produces values scanned 751 * from the specified string. 752 * 753 * @param source A string to scan 754 */ 755 public Scanner(String source) { 756 this(new StringReader(source), WHITESPACE_PATTERN); 757 } 758 759 /** 760 * Constructs a new <code>Scanner</code> that produces values scanned 761 * from the specified channel. Bytes from the source are converted into 762 * characters using the underlying platform's 763 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}. 764 * 765 * @param source A channel to scan 766 */ 767 public Scanner(ReadableByteChannel source) { 768 this(makeReadable(Objects.requireNonNull(source, "source")), 769 WHITESPACE_PATTERN); 770 } 771 772 private static Readable makeReadable(ReadableByteChannel source) { 773 return makeReadable(source, Charset.defaultCharset().newDecoder()); 774 } 775 776 /** 777 * Constructs a new <code>Scanner</code> that produces values scanned 778 * from the specified channel. Bytes from the source are converted into 779 * characters using the specified charset. 780 * 781 * @param source A channel to scan 782 * @param charsetName The encoding type used to convert bytes from the 783 * channel into characters to be scanned 784 * @throws IllegalArgumentException if the specified character set 785 * does not exist 786 */ 787 public Scanner(ReadableByteChannel source, String charsetName) { 788 this(makeReadable(Objects.requireNonNull(source, "source"), toDecoder(charsetName)), 789 WHITESPACE_PATTERN); 790 } 791 792 // Private primitives used to support scanning 793 794 private void saveState() { 795 savedScannerPosition = position; 796 } 797 798 private void revertState() { 799 this.position = savedScannerPosition; 800 savedScannerPosition = -1; 801 skipped = false; 802 } 803 804 private boolean revertState(boolean b) { 805 this.position = savedScannerPosition; 806 savedScannerPosition = -1; 807 skipped = false; 808 return b; 809 } 810 811 private void cacheResult() { 812 hasNextResult = matcher.group(); 813 hasNextPosition = matcher.end(); 814 hasNextPattern = matcher.pattern(); 815 } 816 817 private void cacheResult(String result) { 818 hasNextResult = result; 819 hasNextPosition = matcher.end(); 820 hasNextPattern = matcher.pattern(); 821 } 822 823 // Clears both regular cache and type cache 824 private void clearCaches() { 825 hasNextPattern = null; 826 typeCache = null; 827 } 828 829 // Also clears both the regular cache and the type cache 830 private String getCachedResult() { 831 position = hasNextPosition; 832 hasNextPattern = null; 833 typeCache = null; 834 return hasNextResult; 835 } 836 837 // Also clears both the regular cache and the type cache 838 private void useTypeCache() { 839 if (closed) 840 throw new IllegalStateException("Scanner closed"); 841 position = hasNextPosition; 842 hasNextPattern = null; 843 typeCache = null; 844 } 845 846 // Tries to read more input. May block. 847 private void readInput() { 848 if (buf.limit() == buf.capacity()) 849 makeSpace(); 850 851 // Prepare to receive data 852 int p = buf.position(); 853 buf.position(buf.limit()); 854 buf.limit(buf.capacity()); 855 856 int n = 0; 857 try { 858 n = source.read(buf); 859 } catch (IOException ioe) { 860 lastException = ioe; 861 n = -1; 862 } 863 864 if (n == -1) { 865 sourceClosed = true; 866 needInput = false; 867 } 868 869 if (n > 0) 870 needInput = false; 871 872 // Restore current position and limit for reading 873 buf.limit(buf.position()); 874 buf.position(p); 875 // Android changed : The matcher implementation eagerly calls toString() so we'll have 876 // to update its input whenever the buffer limit, position etc. changes. 877 matcher.reset(buf); 878 } 879 880 // After this method is called there will either be an exception 881 // or else there will be space in the buffer 882 private boolean makeSpace() { 883 clearCaches(); 884 int offset = savedScannerPosition == -1 ? 885 position : savedScannerPosition; 886 buf.position(offset); 887 // Gain space by compacting buffer 888 if (offset > 0) { 889 buf.compact(); 890 translateSavedIndexes(offset); 891 position -= offset; 892 buf.flip(); 893 return true; 894 } 895 // Gain space by growing buffer 896 int newSize = buf.capacity() * 2; 897 CharBuffer newBuf = CharBuffer.allocate(newSize); 898 newBuf.put(buf); 899 newBuf.flip(); 900 translateSavedIndexes(offset); 901 position -= offset; 902 buf = newBuf; 903 matcher.reset(buf); 904 return true; 905 } 906 907 // When a buffer compaction/reallocation occurs the saved indexes must 908 // be modified appropriately 909 private void translateSavedIndexes(int offset) { 910 if (savedScannerPosition != -1) 911 savedScannerPosition -= offset; 912 } 913 914 // If we are at the end of input then NoSuchElement; 915 // If there is still input left then InputMismatch 916 private void throwFor() { 917 skipped = false; 918 if ((sourceClosed) && (position == buf.limit())) 919 throw new NoSuchElementException(); 920 else 921 throw new InputMismatchException(); 922 } 923 924 // Returns true if a complete token or partial token is in the buffer. 925 // It is not necessary to find a complete token since a partial token 926 // means that there will be another token with or without more input. 927 private boolean hasTokenInBuffer() { 928 matchValid = false; 929 matcher.usePattern(delimPattern); 930 matcher.region(position, buf.limit()); 931 932 // Skip delims first 933 if (matcher.lookingAt()) 934 position = matcher.end(); 935 936 // If we are sitting at the end, no more tokens in buffer 937 if (position == buf.limit()) 938 return false; 939 940 return true; 941 } 942 943 /* 944 * Returns a "complete token" that matches the specified pattern 945 * 946 * A token is complete if surrounded by delims; a partial token 947 * is prefixed by delims but not postfixed by them 948 * 949 * The position is advanced to the end of that complete token 950 * 951 * Pattern == null means accept any token at all 952 * 953 * Triple return: 954 * 1. valid string means it was found 955 * 2. null with needInput=false means we won't ever find it 956 * 3. null with needInput=true means try again after readInput 957 */ 958 private String getCompleteTokenInBuffer(Pattern pattern) { 959 matchValid = false; 960 961 // Skip delims first 962 matcher.usePattern(delimPattern); 963 if (!skipped) { // Enforcing only one skip of leading delims 964 matcher.region(position, buf.limit()); 965 if (matcher.lookingAt()) { 966 // If more input could extend the delimiters then we must wait 967 // for more input 968 if (matcher.hitEnd() && !sourceClosed) { 969 needInput = true; 970 return null; 971 } 972 // The delims were whole and the matcher should skip them 973 skipped = true; 974 position = matcher.end(); 975 } 976 } 977 978 // If we are sitting at the end, no more tokens in buffer 979 if (position == buf.limit()) { 980 if (sourceClosed) 981 return null; 982 needInput = true; 983 return null; 984 } 985 986 // Must look for next delims. Simply attempting to match the 987 // pattern at this point may find a match but it might not be 988 // the first longest match because of missing input, or it might 989 // match a partial token instead of the whole thing. 990 991 // Then look for next delims 992 matcher.region(position, buf.limit()); 993 boolean foundNextDelim = matcher.find(); 994 if (foundNextDelim && (matcher.end() == position)) { 995 // Zero length delimiter match; we should find the next one 996 // using the automatic advance past a zero length match; 997 // Otherwise we have just found the same one we just skipped 998 foundNextDelim = matcher.find(); 999 } 1000 if (foundNextDelim) { 1001 // In the rare case that more input could cause the match 1002 // to be lost and there is more input coming we must wait 1003 // for more input. Note that hitting the end is okay as long 1004 // as the match cannot go away. It is the beginning of the 1005 // next delims we want to be sure about, we don't care if 1006 // they potentially extend further. 1007 if (matcher.requireEnd() && !sourceClosed) { 1008 needInput = true; 1009 return null; 1010 } 1011 int tokenEnd = matcher.start(); 1012 // There is a complete token. 1013 if (pattern == null) { 1014 // Must continue with match to provide valid MatchResult 1015 pattern = FIND_ANY_PATTERN; 1016 } 1017 // Attempt to match against the desired pattern 1018 matcher.usePattern(pattern); 1019 matcher.region(position, tokenEnd); 1020 if (matcher.matches()) { 1021 String s = matcher.group(); 1022 position = matcher.end(); 1023 return s; 1024 } else { // Complete token but it does not match 1025 return null; 1026 } 1027 } 1028 1029 // If we can't find the next delims but no more input is coming, 1030 // then we can treat the remainder as a whole token 1031 if (sourceClosed) { 1032 if (pattern == null) { 1033 // Must continue with match to provide valid MatchResult 1034 pattern = FIND_ANY_PATTERN; 1035 } 1036 // Last token; Match the pattern here or throw 1037 matcher.usePattern(pattern); 1038 matcher.region(position, buf.limit()); 1039 if (matcher.matches()) { 1040 String s = matcher.group(); 1041 position = matcher.end(); 1042 return s; 1043 } 1044 // Last piece does not match 1045 return null; 1046 } 1047 1048 // There is a partial token in the buffer; must read more 1049 // to complete it 1050 needInput = true; 1051 return null; 1052 } 1053 1054 // Finds the specified pattern in the buffer up to horizon. 1055 // Returns a match for the specified input pattern. 1056 private String findPatternInBuffer(Pattern pattern, int horizon) { 1057 matchValid = false; 1058 matcher.usePattern(pattern); 1059 int bufferLimit = buf.limit(); 1060 int horizonLimit = -1; 1061 int searchLimit = bufferLimit; 1062 if (horizon > 0) { 1063 horizonLimit = position + horizon; 1064 if (horizonLimit < bufferLimit) 1065 searchLimit = horizonLimit; 1066 } 1067 matcher.region(position, searchLimit); 1068 if (matcher.find()) { 1069 if (matcher.hitEnd() && (!sourceClosed)) { 1070 // The match may be longer if didn't hit horizon or real end 1071 if (searchLimit != horizonLimit) { 1072 // Hit an artificial end; try to extend the match 1073 needInput = true; 1074 return null; 1075 } 1076 // The match could go away depending on what is next 1077 if ((searchLimit == horizonLimit) && matcher.requireEnd()) { 1078 // Rare case: we hit the end of input and it happens 1079 // that it is at the horizon and the end of input is 1080 // required for the match. 1081 needInput = true; 1082 return null; 1083 } 1084 } 1085 // Did not hit end, or hit real end, or hit horizon 1086 position = matcher.end(); 1087 return matcher.group(); 1088 } 1089 1090 if (sourceClosed) 1091 return null; 1092 1093 // If there is no specified horizon, or if we have not searched 1094 // to the specified horizon yet, get more input 1095 if ((horizon == 0) || (searchLimit != horizonLimit)) 1096 needInput = true; 1097 return null; 1098 } 1099 1100 // Returns a match for the specified input pattern anchored at 1101 // the current position 1102 private String matchPatternInBuffer(Pattern pattern) { 1103 matchValid = false; 1104 matcher.usePattern(pattern); 1105 matcher.region(position, buf.limit()); 1106 if (matcher.lookingAt()) { 1107 if (matcher.hitEnd() && (!sourceClosed)) { 1108 // Get more input and try again 1109 needInput = true; 1110 return null; 1111 } 1112 position = matcher.end(); 1113 return matcher.group(); 1114 } 1115 1116 if (sourceClosed) 1117 return null; 1118 1119 // Read more to find pattern 1120 needInput = true; 1121 return null; 1122 } 1123 1124 // Throws if the scanner is closed 1125 private void ensureOpen() { 1126 if (closed) 1127 throw new IllegalStateException("Scanner closed"); 1128 } 1129 1130 // Public methods 1131 1132 /** 1133 * Closes this scanner. 1134 * 1135 * <p> If this scanner has not yet been closed then if its underlying 1136 * {@linkplain java.lang.Readable readable} also implements the {@link 1137 * java.io.Closeable} interface then the readable's <tt>close</tt> method 1138 * will be invoked. If this scanner is already closed then invoking this 1139 * method will have no effect. 1140 * 1141 * <p>Attempting to perform search operations after a scanner has 1142 * been closed will result in an {@link IllegalStateException}. 1143 * 1144 */ 1145 public void close() { 1146 if (closed) 1147 return; 1148 if (source instanceof Closeable) { 1149 try { 1150 ((Closeable)source).close(); 1151 } catch (IOException ioe) { 1152 lastException = ioe; 1153 } 1154 } 1155 sourceClosed = true; 1156 source = null; 1157 closed = true; 1158 } 1159 1160 /** 1161 * Returns the <code>IOException</code> last thrown by this 1162 * <code>Scanner</code>'s underlying <code>Readable</code>. This method 1163 * returns <code>null</code> if no such exception exists. 1164 * 1165 * @return the last exception thrown by this scanner's readable 1166 */ 1167 public IOException ioException() { 1168 return lastException; 1169 } 1170 1171 /** 1172 * Returns the <code>Pattern</code> this <code>Scanner</code> is currently 1173 * using to match delimiters. 1174 * 1175 * @return this scanner's delimiting pattern. 1176 */ 1177 public Pattern delimiter() { 1178 return delimPattern; 1179 } 1180 1181 /** 1182 * Sets this scanner's delimiting pattern to the specified pattern. 1183 * 1184 * @param pattern A delimiting pattern 1185 * @return this scanner 1186 */ 1187 public Scanner useDelimiter(Pattern pattern) { 1188 delimPattern = pattern; 1189 return this; 1190 } 1191 1192 /** 1193 * Sets this scanner's delimiting pattern to a pattern constructed from 1194 * the specified <code>String</code>. 1195 * 1196 * <p> An invocation of this method of the form 1197 * <tt>useDelimiter(pattern)</tt> behaves in exactly the same way as the 1198 * invocation <tt>useDelimiter(Pattern.compile(pattern))</tt>. 1199 * 1200 * <p> Invoking the {@link #reset} method will set the scanner's delimiter 1201 * to the <a href= "#default-delimiter">default</a>. 1202 * 1203 * @param pattern A string specifying a delimiting pattern 1204 * @return this scanner 1205 */ 1206 public Scanner useDelimiter(String pattern) { 1207 delimPattern = patternCache.forName(pattern); 1208 return this; 1209 } 1210 1211 /** 1212 * Returns this scanner's locale. 1213 * 1214 * <p>A scanner's locale affects many elements of its default 1215 * primitive matching regular expressions; see 1216 * <a href= "#localized-numbers">localized numbers</a> above. 1217 * 1218 * @return this scanner's locale 1219 */ 1220 public Locale locale() { 1221 return this.locale; 1222 } 1223 1224 /** 1225 * Sets this scanner's locale to the specified locale. 1226 * 1227 * <p>A scanner's locale affects many elements of its default 1228 * primitive matching regular expressions; see 1229 * <a href= "#localized-numbers">localized numbers</a> above. 1230 * 1231 * <p>Invoking the {@link #reset} method will set the scanner's locale to 1232 * the <a href= "#initial-locale">initial locale</a>. 1233 * 1234 * @param locale A string specifying the locale to use 1235 * @return this scanner 1236 */ 1237 public Scanner useLocale(Locale locale) { 1238 if (locale.equals(this.locale)) 1239 return this; 1240 1241 this.locale = locale; 1242 DecimalFormat df = 1243 (DecimalFormat)NumberFormat.getNumberInstance(locale); 1244 DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale); 1245 1246 // These must be literalized to avoid collision with regex 1247 // metacharacters such as dot or parenthesis 1248 groupSeparator = "\\" + dfs.getGroupingSeparator(); 1249 decimalSeparator = "\\" + dfs.getDecimalSeparator(); 1250 1251 // Quoting the nonzero length locale-specific things 1252 // to avoid potential conflict with metacharacters 1253 nanString = "\\Q" + dfs.getNaN() + "\\E"; 1254 infinityString = "\\Q" + dfs.getInfinity() + "\\E"; 1255 positivePrefix = df.getPositivePrefix(); 1256 if (positivePrefix.length() > 0) 1257 positivePrefix = "\\Q" + positivePrefix + "\\E"; 1258 negativePrefix = df.getNegativePrefix(); 1259 if (negativePrefix.length() > 0) 1260 negativePrefix = "\\Q" + negativePrefix + "\\E"; 1261 positiveSuffix = df.getPositiveSuffix(); 1262 if (positiveSuffix.length() > 0) 1263 positiveSuffix = "\\Q" + positiveSuffix + "\\E"; 1264 negativeSuffix = df.getNegativeSuffix(); 1265 if (negativeSuffix.length() > 0) 1266 negativeSuffix = "\\Q" + negativeSuffix + "\\E"; 1267 1268 // Force rebuilding and recompilation of locale dependent 1269 // primitive patterns 1270 integerPattern = null; 1271 floatPattern = null; 1272 1273 return this; 1274 } 1275 1276 /** 1277 * Returns this scanner's default radix. 1278 * 1279 * <p>A scanner's radix affects elements of its default 1280 * number matching regular expressions; see 1281 * <a href= "#localized-numbers">localized numbers</a> above. 1282 * 1283 * @return the default radix of this scanner 1284 */ 1285 public int radix() { 1286 return this.defaultRadix; 1287 } 1288 1289 /** 1290 * Sets this scanner's default radix to the specified radix. 1291 * 1292 * <p>A scanner's radix affects elements of its default 1293 * number matching regular expressions; see 1294 * <a href= "#localized-numbers">localized numbers</a> above. 1295 * 1296 * <p>If the radix is less than <code>Character.MIN_RADIX</code> 1297 * or greater than <code>Character.MAX_RADIX</code>, then an 1298 * <code>IllegalArgumentException</code> is thrown. 1299 * 1300 * <p>Invoking the {@link #reset} method will set the scanner's radix to 1301 * <code>10</code>. 1302 * 1303 * @param radix The radix to use when scanning numbers 1304 * @return this scanner 1305 * @throws IllegalArgumentException if radix is out of range 1306 */ 1307 public Scanner useRadix(int radix) { 1308 if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX)) 1309 throw new IllegalArgumentException("radix:"+radix); 1310 1311 if (this.defaultRadix == radix) 1312 return this; 1313 this.defaultRadix = radix; 1314 // Force rebuilding and recompilation of radix dependent patterns 1315 integerPattern = null; 1316 return this; 1317 } 1318 1319 // The next operation should occur in the specified radix but 1320 // the default is left untouched. 1321 private void setRadix(int radix) { 1322 // Android-changed : Complain loudly if a bogus radix is being set. 1323 if (radix > Character.MAX_RADIX) { 1324 throw new IllegalArgumentException("radix == " + radix); 1325 } 1326 1327 if (this.radix != radix) { 1328 // Force rebuilding and recompilation of radix dependent patterns 1329 integerPattern = null; 1330 this.radix = radix; 1331 } 1332 } 1333 1334 /** 1335 * Returns the match result of the last scanning operation performed 1336 * by this scanner. This method throws <code>IllegalStateException</code> 1337 * if no match has been performed, or if the last match was 1338 * not successful. 1339 * 1340 * <p>The various <code>next</code>methods of <code>Scanner</code> 1341 * make a match result available if they complete without throwing an 1342 * exception. For instance, after an invocation of the {@link #nextInt} 1343 * method that returned an int, this method returns a 1344 * <code>MatchResult</code> for the search of the 1345 * <a href="#Integer-regex"><i>Integer</i></a> regular expression 1346 * defined above. Similarly the {@link #findInLine}, 1347 * {@link #findWithinHorizon}, and {@link #skip} methods will make a 1348 * match available if they succeed. 1349 * 1350 * @return a match result for the last match operation 1351 * @throws IllegalStateException If no match result is available 1352 */ 1353 public MatchResult match() { 1354 if (!matchValid) 1355 throw new IllegalStateException("No match result available"); 1356 return matcher.toMatchResult(); 1357 } 1358 1359 /** 1360 * <p>Returns the string representation of this <code>Scanner</code>. The 1361 * string representation of a <code>Scanner</code> contains information 1362 * that may be useful for debugging. The exact format is unspecified. 1363 * 1364 * @return The string representation of this scanner 1365 */ 1366 public String toString() { 1367 StringBuilder sb = new StringBuilder(); 1368 sb.append("java.util.Scanner"); 1369 sb.append("[delimiters=" + delimPattern + "]"); 1370 sb.append("[position=" + position + "]"); 1371 sb.append("[match valid=" + matchValid + "]"); 1372 sb.append("[need input=" + needInput + "]"); 1373 sb.append("[source closed=" + sourceClosed + "]"); 1374 sb.append("[skipped=" + skipped + "]"); 1375 sb.append("[group separator=" + groupSeparator + "]"); 1376 sb.append("[decimal separator=" + decimalSeparator + "]"); 1377 sb.append("[positive prefix=" + positivePrefix + "]"); 1378 sb.append("[negative prefix=" + negativePrefix + "]"); 1379 sb.append("[positive suffix=" + positiveSuffix + "]"); 1380 sb.append("[negative suffix=" + negativeSuffix + "]"); 1381 sb.append("[NaN string=" + nanString + "]"); 1382 sb.append("[infinity string=" + infinityString + "]"); 1383 return sb.toString(); 1384 } 1385 1386 /** 1387 * Returns true if this scanner has another token in its input. 1388 * This method may block while waiting for input to scan. 1389 * The scanner does not advance past any input. 1390 * 1391 * @return true if and only if this scanner has another token 1392 * @throws IllegalStateException if this scanner is closed 1393 * @see java.util.Iterator 1394 */ 1395 public boolean hasNext() { 1396 ensureOpen(); 1397 saveState(); 1398 while (!sourceClosed) { 1399 if (hasTokenInBuffer()) 1400 return revertState(true); 1401 readInput(); 1402 } 1403 boolean result = hasTokenInBuffer(); 1404 return revertState(result); 1405 } 1406 1407 /** 1408 * Finds and returns the next complete token from this scanner. 1409 * A complete token is preceded and followed by input that matches 1410 * the delimiter pattern. This method may block while waiting for input 1411 * to scan, even if a previous invocation of {@link #hasNext} returned 1412 * <code>true</code>. 1413 * 1414 * @return the next token 1415 * @throws NoSuchElementException if no more tokens are available 1416 * @throws IllegalStateException if this scanner is closed 1417 * @see java.util.Iterator 1418 */ 1419 public String next() { 1420 ensureOpen(); 1421 clearCaches(); 1422 1423 while (true) { 1424 String token = getCompleteTokenInBuffer(null); 1425 if (token != null) { 1426 matchValid = true; 1427 skipped = false; 1428 return token; 1429 } 1430 if (needInput) 1431 readInput(); 1432 else 1433 throwFor(); 1434 } 1435 } 1436 1437 /** 1438 * The remove operation is not supported by this implementation of 1439 * <code>Iterator</code>. 1440 * 1441 * @throws UnsupportedOperationException if this method is invoked. 1442 * @see java.util.Iterator 1443 */ 1444 public void remove() { 1445 throw new UnsupportedOperationException(); 1446 } 1447 1448 /** 1449 * Returns true if the next token matches the pattern constructed from the 1450 * specified string. The scanner does not advance past any input. 1451 * 1452 * <p> An invocation of this method of the form <tt>hasNext(pattern)</tt> 1453 * behaves in exactly the same way as the invocation 1454 * <tt>hasNext(Pattern.compile(pattern))</tt>. 1455 * 1456 * @param pattern a string specifying the pattern to scan 1457 * @return true if and only if this scanner has another token matching 1458 * the specified pattern 1459 * @throws IllegalStateException if this scanner is closed 1460 */ 1461 public boolean hasNext(String pattern) { 1462 return hasNext(patternCache.forName(pattern)); 1463 } 1464 1465 /** 1466 * Returns the next token if it matches the pattern constructed from the 1467 * specified string. If the match is successful, the scanner advances 1468 * past the input that matched the pattern. 1469 * 1470 * <p> An invocation of this method of the form <tt>next(pattern)</tt> 1471 * behaves in exactly the same way as the invocation 1472 * <tt>next(Pattern.compile(pattern))</tt>. 1473 * 1474 * @param pattern a string specifying the pattern to scan 1475 * @return the next token 1476 * @throws NoSuchElementException if no such tokens are available 1477 * @throws IllegalStateException if this scanner is closed 1478 */ 1479 public String next(String pattern) { 1480 return next(patternCache.forName(pattern)); 1481 } 1482 1483 /** 1484 * Returns true if the next complete token matches the specified pattern. 1485 * A complete token is prefixed and postfixed by input that matches 1486 * the delimiter pattern. This method may block while waiting for input. 1487 * The scanner does not advance past any input. 1488 * 1489 * @param pattern the pattern to scan for 1490 * @return true if and only if this scanner has another token matching 1491 * the specified pattern 1492 * @throws IllegalStateException if this scanner is closed 1493 */ 1494 public boolean hasNext(Pattern pattern) { 1495 ensureOpen(); 1496 if (pattern == null) 1497 throw new NullPointerException(); 1498 hasNextPattern = null; 1499 saveState(); 1500 1501 while (true) { 1502 if (getCompleteTokenInBuffer(pattern) != null) { 1503 matchValid = true; 1504 cacheResult(); 1505 return revertState(true); 1506 } 1507 if (needInput) 1508 readInput(); 1509 else 1510 return revertState(false); 1511 } 1512 } 1513 1514 /** 1515 * Returns the next token if it matches the specified pattern. This 1516 * method may block while waiting for input to scan, even if a previous 1517 * invocation of {@link #hasNext(Pattern)} returned <code>true</code>. 1518 * If the match is successful, the scanner advances past the input that 1519 * matched the pattern. 1520 * 1521 * @param pattern the pattern to scan for 1522 * @return the next token 1523 * @throws NoSuchElementException if no more tokens are available 1524 * @throws IllegalStateException if this scanner is closed 1525 */ 1526 public String next(Pattern pattern) { 1527 ensureOpen(); 1528 if (pattern == null) 1529 throw new NullPointerException(); 1530 1531 // Did we already find this pattern? 1532 if (hasNextPattern == pattern) 1533 return getCachedResult(); 1534 clearCaches(); 1535 1536 // Search for the pattern 1537 while (true) { 1538 String token = getCompleteTokenInBuffer(pattern); 1539 if (token != null) { 1540 matchValid = true; 1541 skipped = false; 1542 return token; 1543 } 1544 if (needInput) 1545 readInput(); 1546 else 1547 throwFor(); 1548 } 1549 } 1550 1551 /** 1552 * Returns true if there is another line in the input of this scanner. 1553 * This method may block while waiting for input. The scanner does not 1554 * advance past any input. 1555 * 1556 * @return true if and only if this scanner has another line of input 1557 * @throws IllegalStateException if this scanner is closed 1558 */ 1559 public boolean hasNextLine() { 1560 saveState(); 1561 1562 String result = findWithinHorizon(linePattern(), 0); 1563 if (result != null) { 1564 MatchResult mr = this.match(); 1565 String lineSep = mr.group(1); 1566 if (lineSep != null) { 1567 result = result.substring(0, result.length() - 1568 lineSep.length()); 1569 cacheResult(result); 1570 1571 } else { 1572 cacheResult(); 1573 } 1574 } 1575 revertState(); 1576 return (result != null); 1577 } 1578 1579 /** 1580 * Advances this scanner past the current line and returns the input 1581 * that was skipped. 1582 * 1583 * This method returns the rest of the current line, excluding any line 1584 * separator at the end. The position is set to the beginning of the next 1585 * line. 1586 * 1587 * <p>Since this method continues to search through the input looking 1588 * for a line separator, it may buffer all of the input searching for 1589 * the line to skip if no line separators are present. 1590 * 1591 * @return the line that was skipped 1592 * @throws NoSuchElementException if no line was found 1593 * @throws IllegalStateException if this scanner is closed 1594 */ 1595 public String nextLine() { 1596 if (hasNextPattern == linePattern()) 1597 return getCachedResult(); 1598 clearCaches(); 1599 1600 String result = findWithinHorizon(linePattern, 0); 1601 if (result == null) 1602 throw new NoSuchElementException("No line found"); 1603 MatchResult mr = this.match(); 1604 String lineSep = mr.group(1); 1605 if (lineSep != null) 1606 result = result.substring(0, result.length() - lineSep.length()); 1607 if (result == null) 1608 throw new NoSuchElementException(); 1609 else 1610 return result; 1611 } 1612 1613 // Public methods that ignore delimiters 1614 1615 /** 1616 * Attempts to find the next occurrence of a pattern constructed from the 1617 * specified string, ignoring delimiters. 1618 * 1619 * <p>An invocation of this method of the form <tt>findInLine(pattern)</tt> 1620 * behaves in exactly the same way as the invocation 1621 * <tt>findInLine(Pattern.compile(pattern))</tt>. 1622 * 1623 * @param pattern a string specifying the pattern to search for 1624 * @return the text that matched the specified pattern 1625 * @throws IllegalStateException if this scanner is closed 1626 */ 1627 public String findInLine(String pattern) { 1628 return findInLine(patternCache.forName(pattern)); 1629 } 1630 1631 /** 1632 * Attempts to find the next occurrence of the specified pattern ignoring 1633 * delimiters. If the pattern is found before the next line separator, the 1634 * scanner advances past the input that matched and returns the string that 1635 * matched the pattern. 1636 * If no such pattern is detected in the input up to the next line 1637 * separator, then <code>null</code> is returned and the scanner's 1638 * position is unchanged. This method may block waiting for input that 1639 * matches the pattern. 1640 * 1641 * <p>Since this method continues to search through the input looking 1642 * for the specified pattern, it may buffer all of the input searching for 1643 * the desired token if no line separators are present. 1644 * 1645 * @param pattern the pattern to scan for 1646 * @return the text that matched the specified pattern 1647 * @throws IllegalStateException if this scanner is closed 1648 */ 1649 public String findInLine(Pattern pattern) { 1650 ensureOpen(); 1651 if (pattern == null) 1652 throw new NullPointerException(); 1653 clearCaches(); 1654 // Expand buffer to include the next newline or end of input 1655 int endPosition = 0; 1656 saveState(); 1657 while (true) { 1658 String token = findPatternInBuffer(separatorPattern(), 0); 1659 if (token != null) { 1660 endPosition = matcher.start(); 1661 break; // up to next newline 1662 } 1663 if (needInput) { 1664 readInput(); 1665 } else { 1666 endPosition = buf.limit(); 1667 break; // up to end of input 1668 } 1669 } 1670 revertState(); 1671 int horizonForLine = endPosition - position; 1672 // If there is nothing between the current pos and the next 1673 // newline simply return null, invoking findWithinHorizon 1674 // with "horizon=0" will scan beyond the line bound. 1675 if (horizonForLine == 0) 1676 return null; 1677 // Search for the pattern 1678 return findWithinHorizon(pattern, horizonForLine); 1679 } 1680 1681 /** 1682 * Attempts to find the next occurrence of a pattern constructed from the 1683 * specified string, ignoring delimiters. 1684 * 1685 * <p>An invocation of this method of the form 1686 * <tt>findWithinHorizon(pattern)</tt> behaves in exactly the same way as 1687 * the invocation 1688 * <tt>findWithinHorizon(Pattern.compile(pattern, horizon))</tt>. 1689 * 1690 * @param pattern a string specifying the pattern to search for 1691 * @return the text that matched the specified pattern 1692 * @throws IllegalStateException if this scanner is closed 1693 * @throws IllegalArgumentException if horizon is negative 1694 */ 1695 public String findWithinHorizon(String pattern, int horizon) { 1696 return findWithinHorizon(patternCache.forName(pattern), horizon); 1697 } 1698 1699 /** 1700 * Attempts to find the next occurrence of the specified pattern. 1701 * 1702 * <p>This method searches through the input up to the specified 1703 * search horizon, ignoring delimiters. If the pattern is found the 1704 * scanner advances past the input that matched and returns the string 1705 * that matched the pattern. If no such pattern is detected then the 1706 * null is returned and the scanner's position remains unchanged. This 1707 * method may block waiting for input that matches the pattern. 1708 * 1709 * <p>A scanner will never search more than <code>horizon</code> code 1710 * points beyond its current position. Note that a match may be clipped 1711 * by the horizon; that is, an arbitrary match result may have been 1712 * different if the horizon had been larger. The scanner treats the 1713 * horizon as a transparent, non-anchoring bound (see {@link 1714 * Matcher#useTransparentBounds} and {@link Matcher#useAnchoringBounds}). 1715 * 1716 * <p>If horizon is <code>0</code>, then the horizon is ignored and 1717 * this method continues to search through the input looking for the 1718 * specified pattern without bound. In this case it may buffer all of 1719 * the input searching for the pattern. 1720 * 1721 * <p>If horizon is negative, then an IllegalArgumentException is 1722 * thrown. 1723 * 1724 * @param pattern the pattern to scan for 1725 * @return the text that matched the specified pattern 1726 * @throws IllegalStateException if this scanner is closed 1727 * @throws IllegalArgumentException if horizon is negative 1728 */ 1729 public String findWithinHorizon(Pattern pattern, int horizon) { 1730 ensureOpen(); 1731 if (pattern == null) 1732 throw new NullPointerException(); 1733 if (horizon < 0) 1734 throw new IllegalArgumentException("horizon < 0"); 1735 clearCaches(); 1736 1737 // Search for the pattern 1738 while (true) { 1739 String token = findPatternInBuffer(pattern, horizon); 1740 if (token != null) { 1741 matchValid = true; 1742 return token; 1743 } 1744 if (needInput) 1745 readInput(); 1746 else 1747 break; // up to end of input 1748 } 1749 return null; 1750 } 1751 1752 /** 1753 * Skips input that matches the specified pattern, ignoring delimiters. 1754 * This method will skip input if an anchored match of the specified 1755 * pattern succeeds. 1756 * 1757 * <p>If a match to the specified pattern is not found at the 1758 * current position, then no input is skipped and a 1759 * <tt>NoSuchElementException</tt> is thrown. 1760 * 1761 * <p>Since this method seeks to match the specified pattern starting at 1762 * the scanner's current position, patterns that can match a lot of 1763 * input (".*", for example) may cause the scanner to buffer a large 1764 * amount of input. 1765 * 1766 * <p>Note that it is possible to skip something without risking a 1767 * <code>NoSuchElementException</code> by using a pattern that can 1768 * match nothing, e.g., <code>sc.skip("[ \t]*")</code>. 1769 * 1770 * @param pattern a string specifying the pattern to skip over 1771 * @return this scanner 1772 * @throws NoSuchElementException if the specified pattern is not found 1773 * @throws IllegalStateException if this scanner is closed 1774 */ 1775 public Scanner skip(Pattern pattern) { 1776 ensureOpen(); 1777 if (pattern == null) 1778 throw new NullPointerException(); 1779 clearCaches(); 1780 1781 // Search for the pattern 1782 while (true) { 1783 String token = matchPatternInBuffer(pattern); 1784 if (token != null) { 1785 matchValid = true; 1786 position = matcher.end(); 1787 return this; 1788 } 1789 if (needInput) 1790 readInput(); 1791 else 1792 throw new NoSuchElementException(); 1793 } 1794 } 1795 1796 /** 1797 * Skips input that matches a pattern constructed from the specified 1798 * string. 1799 * 1800 * <p> An invocation of this method of the form <tt>skip(pattern)</tt> 1801 * behaves in exactly the same way as the invocation 1802 * <tt>skip(Pattern.compile(pattern))</tt>. 1803 * 1804 * @param pattern a string specifying the pattern to skip over 1805 * @return this scanner 1806 * @throws IllegalStateException if this scanner is closed 1807 */ 1808 public Scanner skip(String pattern) { 1809 return skip(patternCache.forName(pattern)); 1810 } 1811 1812 // Convenience methods for scanning primitives 1813 1814 /** 1815 * Returns true if the next token in this scanner's input can be 1816 * interpreted as a boolean value using a case insensitive pattern 1817 * created from the string "true|false". The scanner does not 1818 * advance past the input that matched. 1819 * 1820 * @return true if and only if this scanner's next token is a valid 1821 * boolean value 1822 * @throws IllegalStateException if this scanner is closed 1823 */ 1824 public boolean hasNextBoolean() { 1825 return hasNext(boolPattern()); 1826 } 1827 1828 /** 1829 * Scans the next token of the input into a boolean value and returns 1830 * that value. This method will throw <code>InputMismatchException</code> 1831 * if the next token cannot be translated into a valid boolean value. 1832 * If the match is successful, the scanner advances past the input that 1833 * matched. 1834 * 1835 * @return the boolean scanned from the input 1836 * @throws InputMismatchException if the next token is not a valid boolean 1837 * @throws NoSuchElementException if input is exhausted 1838 * @throws IllegalStateException if this scanner is closed 1839 */ 1840 public boolean nextBoolean() { 1841 clearCaches(); 1842 return Boolean.parseBoolean(next(boolPattern())); 1843 } 1844 1845 /** 1846 * Returns true if the next token in this scanner's input can be 1847 * interpreted as a byte value in the default radix using the 1848 * {@link #nextByte} method. The scanner does not advance past any input. 1849 * 1850 * @return true if and only if this scanner's next token is a valid 1851 * byte value 1852 * @throws IllegalStateException if this scanner is closed 1853 */ 1854 public boolean hasNextByte() { 1855 return hasNextByte(defaultRadix); 1856 } 1857 1858 /** 1859 * Returns true if the next token in this scanner's input can be 1860 * interpreted as a byte value in the specified radix using the 1861 * {@link #nextByte} method. The scanner does not advance past any input. 1862 * 1863 * @param radix the radix used to interpret the token as a byte value 1864 * @return true if and only if this scanner's next token is a valid 1865 * byte value 1866 * @throws IllegalStateException if this scanner is closed 1867 */ 1868 public boolean hasNextByte(int radix) { 1869 setRadix(radix); 1870 boolean result = hasNext(integerPattern()); 1871 if (result) { // Cache it 1872 try { 1873 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? 1874 processIntegerToken(hasNextResult) : 1875 hasNextResult; 1876 typeCache = Byte.parseByte(s, radix); 1877 } catch (NumberFormatException nfe) { 1878 result = false; 1879 } 1880 } 1881 return result; 1882 } 1883 1884 /** 1885 * Scans the next token of the input as a <tt>byte</tt>. 1886 * 1887 * <p> An invocation of this method of the form 1888 * <tt>nextByte()</tt> behaves in exactly the same way as the 1889 * invocation <tt>nextByte(radix)</tt>, where <code>radix</code> 1890 * is the default radix of this scanner. 1891 * 1892 * @return the <tt>byte</tt> scanned from the input 1893 * @throws InputMismatchException 1894 * if the next token does not match the <i>Integer</i> 1895 * regular expression, or is out of range 1896 * @throws NoSuchElementException if input is exhausted 1897 * @throws IllegalStateException if this scanner is closed 1898 */ 1899 public byte nextByte() { 1900 return nextByte(defaultRadix); 1901 } 1902 1903 /** 1904 * Scans the next token of the input as a <tt>byte</tt>. 1905 * This method will throw <code>InputMismatchException</code> 1906 * if the next token cannot be translated into a valid byte value as 1907 * described below. If the translation is successful, the scanner advances 1908 * past the input that matched. 1909 * 1910 * <p> If the next token matches the <a 1911 * href="#Integer-regex"><i>Integer</i></a> regular expression defined 1912 * above then the token is converted into a <tt>byte</tt> value as if by 1913 * removing all locale specific prefixes, group separators, and locale 1914 * specific suffixes, then mapping non-ASCII digits into ASCII 1915 * digits via {@link Character#digit Character.digit}, prepending a 1916 * negative sign (-) if the locale specific negative prefixes and suffixes 1917 * were present, and passing the resulting string to 1918 * {@link Byte#parseByte(String, int) Byte.parseByte} with the 1919 * specified radix. 1920 * 1921 * @param radix the radix used to interpret the token as a byte value 1922 * @return the <tt>byte</tt> scanned from the input 1923 * @throws InputMismatchException 1924 * if the next token does not match the <i>Integer</i> 1925 * regular expression, or is out of range 1926 * @throws NoSuchElementException if input is exhausted 1927 * @throws IllegalStateException if this scanner is closed 1928 */ 1929 public byte nextByte(int radix) { 1930 // Check cached result 1931 if ((typeCache != null) && (typeCache instanceof Byte) 1932 && this.radix == radix) { 1933 byte val = ((Byte)typeCache).byteValue(); 1934 useTypeCache(); 1935 return val; 1936 } 1937 setRadix(radix); 1938 clearCaches(); 1939 // Search for next byte 1940 try { 1941 String s = next(integerPattern()); 1942 if (matcher.group(SIMPLE_GROUP_INDEX) == null) 1943 s = processIntegerToken(s); 1944 return Byte.parseByte(s, radix); 1945 } catch (NumberFormatException nfe) { 1946 position = matcher.start(); // don't skip bad token 1947 throw new InputMismatchException(nfe.getMessage()); 1948 } 1949 } 1950 1951 /** 1952 * Returns true if the next token in this scanner's input can be 1953 * interpreted as a short value in the default radix using the 1954 * {@link #nextShort} method. The scanner does not advance past any input. 1955 * 1956 * @return true if and only if this scanner's next token is a valid 1957 * short value in the default radix 1958 * @throws IllegalStateException if this scanner is closed 1959 */ 1960 public boolean hasNextShort() { 1961 return hasNextShort(defaultRadix); 1962 } 1963 1964 /** 1965 * Returns true if the next token in this scanner's input can be 1966 * interpreted as a short value in the specified radix using the 1967 * {@link #nextShort} method. The scanner does not advance past any input. 1968 * 1969 * @param radix the radix used to interpret the token as a short value 1970 * @return true if and only if this scanner's next token is a valid 1971 * short value in the specified radix 1972 * @throws IllegalStateException if this scanner is closed 1973 */ 1974 public boolean hasNextShort(int radix) { 1975 setRadix(radix); 1976 boolean result = hasNext(integerPattern()); 1977 if (result) { // Cache it 1978 try { 1979 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? 1980 processIntegerToken(hasNextResult) : 1981 hasNextResult; 1982 typeCache = Short.parseShort(s, radix); 1983 } catch (NumberFormatException nfe) { 1984 result = false; 1985 } 1986 } 1987 return result; 1988 } 1989 1990 /** 1991 * Scans the next token of the input as a <tt>short</tt>. 1992 * 1993 * <p> An invocation of this method of the form 1994 * <tt>nextShort()</tt> behaves in exactly the same way as the 1995 * invocation <tt>nextShort(radix)</tt>, where <code>radix</code> 1996 * is the default radix of this scanner. 1997 * 1998 * @return the <tt>short</tt> scanned from the input 1999 * @throws InputMismatchException 2000 * if the next token does not match the <i>Integer</i> 2001 * regular expression, or is out of range 2002 * @throws NoSuchElementException if input is exhausted 2003 * @throws IllegalStateException if this scanner is closed 2004 */ 2005 public short nextShort() { 2006 return nextShort(defaultRadix); 2007 } 2008 2009 /** 2010 * Scans the next token of the input as a <tt>short</tt>. 2011 * This method will throw <code>InputMismatchException</code> 2012 * if the next token cannot be translated into a valid short value as 2013 * described below. If the translation is successful, the scanner advances 2014 * past the input that matched. 2015 * 2016 * <p> If the next token matches the <a 2017 * href="#Integer-regex"><i>Integer</i></a> regular expression defined 2018 * above then the token is converted into a <tt>short</tt> value as if by 2019 * removing all locale specific prefixes, group separators, and locale 2020 * specific suffixes, then mapping non-ASCII digits into ASCII 2021 * digits via {@link Character#digit Character.digit}, prepending a 2022 * negative sign (-) if the locale specific negative prefixes and suffixes 2023 * were present, and passing the resulting string to 2024 * {@link Short#parseShort(String, int) Short.parseShort} with the 2025 * specified radix. 2026 * 2027 * @param radix the radix used to interpret the token as a short value 2028 * @return the <tt>short</tt> scanned from the input 2029 * @throws InputMismatchException 2030 * if the next token does not match the <i>Integer</i> 2031 * regular expression, or is out of range 2032 * @throws NoSuchElementException if input is exhausted 2033 * @throws IllegalStateException if this scanner is closed 2034 */ 2035 public short nextShort(int radix) { 2036 // Check cached result 2037 if ((typeCache != null) && (typeCache instanceof Short) 2038 && this.radix == radix) { 2039 short val = ((Short)typeCache).shortValue(); 2040 useTypeCache(); 2041 return val; 2042 } 2043 setRadix(radix); 2044 clearCaches(); 2045 // Search for next short 2046 try { 2047 String s = next(integerPattern()); 2048 if (matcher.group(SIMPLE_GROUP_INDEX) == null) 2049 s = processIntegerToken(s); 2050 return Short.parseShort(s, radix); 2051 } catch (NumberFormatException nfe) { 2052 position = matcher.start(); // don't skip bad token 2053 throw new InputMismatchException(nfe.getMessage()); 2054 } 2055 } 2056 2057 /** 2058 * Returns true if the next token in this scanner's input can be 2059 * interpreted as an int value in the default radix using the 2060 * {@link #nextInt} method. The scanner does not advance past any input. 2061 * 2062 * @return true if and only if this scanner's next token is a valid 2063 * int value 2064 * @throws IllegalStateException if this scanner is closed 2065 */ 2066 public boolean hasNextInt() { 2067 return hasNextInt(defaultRadix); 2068 } 2069 2070 /** 2071 * Returns true if the next token in this scanner's input can be 2072 * interpreted as an int value in the specified radix using the 2073 * {@link #nextInt} method. The scanner does not advance past any input. 2074 * 2075 * @param radix the radix used to interpret the token as an int value 2076 * @return true if and only if this scanner's next token is a valid 2077 * int value 2078 * @throws IllegalStateException if this scanner is closed 2079 */ 2080 public boolean hasNextInt(int radix) { 2081 setRadix(radix); 2082 boolean result = hasNext(integerPattern()); 2083 if (result) { // Cache it 2084 try { 2085 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? 2086 processIntegerToken(hasNextResult) : 2087 hasNextResult; 2088 typeCache = Integer.parseInt(s, radix); 2089 } catch (NumberFormatException nfe) { 2090 result = false; 2091 } 2092 } 2093 return result; 2094 } 2095 2096 /** 2097 * The integer token must be stripped of prefixes, group separators, 2098 * and suffixes, non ascii digits must be converted into ascii digits 2099 * before parse will accept it. 2100 */ 2101 private String processIntegerToken(String token) { 2102 String result = token.replaceAll(""+groupSeparator, ""); 2103 boolean isNegative = false; 2104 int preLen = negativePrefix.length(); 2105 if ((preLen > 0) && result.startsWith(negativePrefix)) { 2106 isNegative = true; 2107 result = result.substring(preLen); 2108 } 2109 int sufLen = negativeSuffix.length(); 2110 if ((sufLen > 0) && result.endsWith(negativeSuffix)) { 2111 isNegative = true; 2112 result = result.substring(result.length() - sufLen, 2113 result.length()); 2114 } 2115 if (isNegative) 2116 result = "-" + result; 2117 return result; 2118 } 2119 2120 /** 2121 * Scans the next token of the input as an <tt>int</tt>. 2122 * 2123 * <p> An invocation of this method of the form 2124 * <tt>nextInt()</tt> behaves in exactly the same way as the 2125 * invocation <tt>nextInt(radix)</tt>, where <code>radix</code> 2126 * is the default radix of this scanner. 2127 * 2128 * @return the <tt>int</tt> scanned from the input 2129 * @throws InputMismatchException 2130 * if the next token does not match the <i>Integer</i> 2131 * regular expression, or is out of range 2132 * @throws NoSuchElementException if input is exhausted 2133 * @throws IllegalStateException if this scanner is closed 2134 */ 2135 public int nextInt() { 2136 return nextInt(defaultRadix); 2137 } 2138 2139 /** 2140 * Scans the next token of the input as an <tt>int</tt>. 2141 * This method will throw <code>InputMismatchException</code> 2142 * if the next token cannot be translated into a valid int value as 2143 * described below. If the translation is successful, the scanner advances 2144 * past the input that matched. 2145 * 2146 * <p> If the next token matches the <a 2147 * href="#Integer-regex"><i>Integer</i></a> regular expression defined 2148 * above then the token is converted into an <tt>int</tt> value as if by 2149 * removing all locale specific prefixes, group separators, and locale 2150 * specific suffixes, then mapping non-ASCII digits into ASCII 2151 * digits via {@link Character#digit Character.digit}, prepending a 2152 * negative sign (-) if the locale specific negative prefixes and suffixes 2153 * were present, and passing the resulting string to 2154 * {@link Integer#parseInt(String, int) Integer.parseInt} with the 2155 * specified radix. 2156 * 2157 * @param radix the radix used to interpret the token as an int value 2158 * @return the <tt>int</tt> scanned from the input 2159 * @throws InputMismatchException 2160 * if the next token does not match the <i>Integer</i> 2161 * regular expression, or is out of range 2162 * @throws NoSuchElementException if input is exhausted 2163 * @throws IllegalStateException if this scanner is closed 2164 */ 2165 public int nextInt(int radix) { 2166 // Check cached result 2167 if ((typeCache != null) && (typeCache instanceof Integer) 2168 && this.radix == radix) { 2169 int val = ((Integer)typeCache).intValue(); 2170 useTypeCache(); 2171 return val; 2172 } 2173 setRadix(radix); 2174 clearCaches(); 2175 // Search for next int 2176 try { 2177 String s = next(integerPattern()); 2178 if (matcher.group(SIMPLE_GROUP_INDEX) == null) 2179 s = processIntegerToken(s); 2180 return Integer.parseInt(s, radix); 2181 } catch (NumberFormatException nfe) { 2182 position = matcher.start(); // don't skip bad token 2183 throw new InputMismatchException(nfe.getMessage()); 2184 } 2185 } 2186 2187 /** 2188 * Returns true if the next token in this scanner's input can be 2189 * interpreted as a long value in the default radix using the 2190 * {@link #nextLong} method. The scanner does not advance past any input. 2191 * 2192 * @return true if and only if this scanner's next token is a valid 2193 * long value 2194 * @throws IllegalStateException if this scanner is closed 2195 */ 2196 public boolean hasNextLong() { 2197 return hasNextLong(defaultRadix); 2198 } 2199 2200 /** 2201 * Returns true if the next token in this scanner's input can be 2202 * interpreted as a long value in the specified radix using the 2203 * {@link #nextLong} method. The scanner does not advance past any input. 2204 * 2205 * @param radix the radix used to interpret the token as a long value 2206 * @return true if and only if this scanner's next token is a valid 2207 * long value 2208 * @throws IllegalStateException if this scanner is closed 2209 */ 2210 public boolean hasNextLong(int radix) { 2211 setRadix(radix); 2212 boolean result = hasNext(integerPattern()); 2213 if (result) { // Cache it 2214 try { 2215 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? 2216 processIntegerToken(hasNextResult) : 2217 hasNextResult; 2218 typeCache = Long.parseLong(s, radix); 2219 } catch (NumberFormatException nfe) { 2220 result = false; 2221 } 2222 } 2223 return result; 2224 } 2225 2226 /** 2227 * Scans the next token of the input as a <tt>long</tt>. 2228 * 2229 * <p> An invocation of this method of the form 2230 * <tt>nextLong()</tt> behaves in exactly the same way as the 2231 * invocation <tt>nextLong(radix)</tt>, where <code>radix</code> 2232 * is the default radix of this scanner. 2233 * 2234 * @return the <tt>long</tt> scanned from the input 2235 * @throws InputMismatchException 2236 * if the next token does not match the <i>Integer</i> 2237 * regular expression, or is out of range 2238 * @throws NoSuchElementException if input is exhausted 2239 * @throws IllegalStateException if this scanner is closed 2240 */ 2241 public long nextLong() { 2242 return nextLong(defaultRadix); 2243 } 2244 2245 /** 2246 * Scans the next token of the input as a <tt>long</tt>. 2247 * This method will throw <code>InputMismatchException</code> 2248 * if the next token cannot be translated into a valid long value as 2249 * described below. If the translation is successful, the scanner advances 2250 * past the input that matched. 2251 * 2252 * <p> If the next token matches the <a 2253 * href="#Integer-regex"><i>Integer</i></a> regular expression defined 2254 * above then the token is converted into a <tt>long</tt> value as if by 2255 * removing all locale specific prefixes, group separators, and locale 2256 * specific suffixes, then mapping non-ASCII digits into ASCII 2257 * digits via {@link Character#digit Character.digit}, prepending a 2258 * negative sign (-) if the locale specific negative prefixes and suffixes 2259 * were present, and passing the resulting string to 2260 * {@link Long#parseLong(String, int) Long.parseLong} with the 2261 * specified radix. 2262 * 2263 * @param radix the radix used to interpret the token as an int value 2264 * @return the <tt>long</tt> scanned from the input 2265 * @throws InputMismatchException 2266 * if the next token does not match the <i>Integer</i> 2267 * regular expression, or is out of range 2268 * @throws NoSuchElementException if input is exhausted 2269 * @throws IllegalStateException if this scanner is closed 2270 */ 2271 public long nextLong(int radix) { 2272 // Check cached result 2273 if ((typeCache != null) && (typeCache instanceof Long) 2274 && this.radix == radix) { 2275 long val = ((Long)typeCache).longValue(); 2276 useTypeCache(); 2277 return val; 2278 } 2279 setRadix(radix); 2280 clearCaches(); 2281 try { 2282 String s = next(integerPattern()); 2283 if (matcher.group(SIMPLE_GROUP_INDEX) == null) 2284 s = processIntegerToken(s); 2285 return Long.parseLong(s, radix); 2286 } catch (NumberFormatException nfe) { 2287 position = matcher.start(); // don't skip bad token 2288 throw new InputMismatchException(nfe.getMessage()); 2289 } 2290 } 2291 2292 /** 2293 * The float token must be stripped of prefixes, group separators, 2294 * and suffixes, non ascii digits must be converted into ascii digits 2295 * before parseFloat will accept it. 2296 * 2297 * If there are non-ascii digits in the token these digits must 2298 * be processed before the token is passed to parseFloat. 2299 */ 2300 private String processFloatToken(String token) { 2301 String result = token.replaceAll(groupSeparator, ""); 2302 if (!decimalSeparator.equals("\\.")) 2303 result = result.replaceAll(decimalSeparator, "."); 2304 boolean isNegative = false; 2305 int preLen = negativePrefix.length(); 2306 if ((preLen > 0) && result.startsWith(negativePrefix)) { 2307 isNegative = true; 2308 result = result.substring(preLen); 2309 } 2310 int sufLen = negativeSuffix.length(); 2311 if ((sufLen > 0) && result.endsWith(negativeSuffix)) { 2312 isNegative = true; 2313 result = result.substring(result.length() - sufLen, 2314 result.length()); 2315 } 2316 if (result.equals(nanString)) 2317 result = "NaN"; 2318 if (result.equals(infinityString)) 2319 result = "Infinity"; 2320 // Android-changed: Match the infinity symbol. 2321 if (result.equals("\u221E")) 2322 result = "Infinity"; 2323 if (isNegative) 2324 result = "-" + result; 2325 2326 // Translate non-ASCII digits 2327 Matcher m = NON_ASCII_DIGIT.matcher(result); 2328 if (m.find()) { 2329 StringBuilder inASCII = new StringBuilder(); 2330 for (int i=0; i<result.length(); i++) { 2331 char nextChar = result.charAt(i); 2332 if (Character.isDigit(nextChar)) { 2333 int d = Character.digit(nextChar, 10); 2334 if (d != -1) 2335 inASCII.append(d); 2336 else 2337 inASCII.append(nextChar); 2338 } else { 2339 inASCII.append(nextChar); 2340 } 2341 } 2342 result = inASCII.toString(); 2343 } 2344 2345 return result; 2346 } 2347 2348 /** 2349 * Returns true if the next token in this scanner's input can be 2350 * interpreted as a float value using the {@link #nextFloat} 2351 * method. The scanner does not advance past any input. 2352 * 2353 * @return true if and only if this scanner's next token is a valid 2354 * float value 2355 * @throws IllegalStateException if this scanner is closed 2356 */ 2357 public boolean hasNextFloat() { 2358 setRadix(10); 2359 boolean result = hasNext(floatPattern()); 2360 if (result) { // Cache it 2361 try { 2362 String s = processFloatToken(hasNextResult); 2363 typeCache = Float.valueOf(Float.parseFloat(s)); 2364 } catch (NumberFormatException nfe) { 2365 result = false; 2366 } 2367 } 2368 return result; 2369 } 2370 2371 /** 2372 * Scans the next token of the input as a <tt>float</tt>. 2373 * This method will throw <code>InputMismatchException</code> 2374 * if the next token cannot be translated into a valid float value as 2375 * described below. If the translation is successful, the scanner advances 2376 * past the input that matched. 2377 * 2378 * <p> If the next token matches the <a 2379 * href="#Float-regex"><i>Float</i></a> regular expression defined above 2380 * then the token is converted into a <tt>float</tt> value as if by 2381 * removing all locale specific prefixes, group separators, and locale 2382 * specific suffixes, then mapping non-ASCII digits into ASCII 2383 * digits via {@link Character#digit Character.digit}, prepending a 2384 * negative sign (-) if the locale specific negative prefixes and suffixes 2385 * were present, and passing the resulting string to 2386 * {@link Float#parseFloat Float.parseFloat}. If the token matches 2387 * the localized NaN or infinity strings, then either "Nan" or "Infinity" 2388 * is passed to {@link Float#parseFloat(String) Float.parseFloat} as 2389 * appropriate. 2390 * 2391 * @return the <tt>float</tt> scanned from the input 2392 * @throws InputMismatchException 2393 * if the next token does not match the <i>Float</i> 2394 * regular expression, or is out of range 2395 * @throws NoSuchElementException if input is exhausted 2396 * @throws IllegalStateException if this scanner is closed 2397 */ 2398 public float nextFloat() { 2399 // Check cached result 2400 if ((typeCache != null) && (typeCache instanceof Float)) { 2401 float val = ((Float)typeCache).floatValue(); 2402 useTypeCache(); 2403 return val; 2404 } 2405 setRadix(10); 2406 clearCaches(); 2407 try { 2408 return Float.parseFloat(processFloatToken(next(floatPattern()))); 2409 } catch (NumberFormatException nfe) { 2410 position = matcher.start(); // don't skip bad token 2411 throw new InputMismatchException(nfe.getMessage()); 2412 } 2413 } 2414 2415 /** 2416 * Returns true if the next token in this scanner's input can be 2417 * interpreted as a double value using the {@link #nextDouble} 2418 * method. The scanner does not advance past any input. 2419 * 2420 * @return true if and only if this scanner's next token is a valid 2421 * double value 2422 * @throws IllegalStateException if this scanner is closed 2423 */ 2424 public boolean hasNextDouble() { 2425 setRadix(10); 2426 boolean result = hasNext(floatPattern()); 2427 if (result) { // Cache it 2428 try { 2429 String s = processFloatToken(hasNextResult); 2430 typeCache = Double.valueOf(Double.parseDouble(s)); 2431 } catch (NumberFormatException nfe) { 2432 result = false; 2433 } 2434 } 2435 return result; 2436 } 2437 2438 /** 2439 * Scans the next token of the input as a <tt>double</tt>. 2440 * This method will throw <code>InputMismatchException</code> 2441 * if the next token cannot be translated into a valid double value. 2442 * If the translation is successful, the scanner advances past the input 2443 * that matched. 2444 * 2445 * <p> If the next token matches the <a 2446 * href="#Float-regex"><i>Float</i></a> regular expression defined above 2447 * then the token is converted into a <tt>double</tt> value as if by 2448 * removing all locale specific prefixes, group separators, and locale 2449 * specific suffixes, then mapping non-ASCII digits into ASCII 2450 * digits via {@link Character#digit Character.digit}, prepending a 2451 * negative sign (-) if the locale specific negative prefixes and suffixes 2452 * were present, and passing the resulting string to 2453 * {@link Double#parseDouble Double.parseDouble}. If the token matches 2454 * the localized NaN or infinity strings, then either "Nan" or "Infinity" 2455 * is passed to {@link Double#parseDouble(String) Double.parseDouble} as 2456 * appropriate. 2457 * 2458 * @return the <tt>double</tt> scanned from the input 2459 * @throws InputMismatchException 2460 * if the next token does not match the <i>Float</i> 2461 * regular expression, or is out of range 2462 * @throws NoSuchElementException if the input is exhausted 2463 * @throws IllegalStateException if this scanner is closed 2464 */ 2465 public double nextDouble() { 2466 // Check cached result 2467 if ((typeCache != null) && (typeCache instanceof Double)) { 2468 double val = ((Double)typeCache).doubleValue(); 2469 useTypeCache(); 2470 return val; 2471 } 2472 setRadix(10); 2473 clearCaches(); 2474 // Search for next float 2475 try { 2476 return Double.parseDouble(processFloatToken(next(floatPattern()))); 2477 } catch (NumberFormatException nfe) { 2478 position = matcher.start(); // don't skip bad token 2479 throw new InputMismatchException(nfe.getMessage()); 2480 } 2481 } 2482 2483 // Convenience methods for scanning multi precision numbers 2484 2485 /** 2486 * Returns true if the next token in this scanner's input can be 2487 * interpreted as a <code>BigInteger</code> in the default radix using the 2488 * {@link #nextBigInteger} method. The scanner does not advance past any 2489 * input. 2490 * 2491 * @return true if and only if this scanner's next token is a valid 2492 * <code>BigInteger</code> 2493 * @throws IllegalStateException if this scanner is closed 2494 */ 2495 public boolean hasNextBigInteger() { 2496 return hasNextBigInteger(defaultRadix); 2497 } 2498 2499 /** 2500 * Returns true if the next token in this scanner's input can be 2501 * interpreted as a <code>BigInteger</code> in the specified radix using 2502 * the {@link #nextBigInteger} method. The scanner does not advance past 2503 * any input. 2504 * 2505 * @param radix the radix used to interpret the token as an integer 2506 * @return true if and only if this scanner's next token is a valid 2507 * <code>BigInteger</code> 2508 * @throws IllegalStateException if this scanner is closed 2509 */ 2510 public boolean hasNextBigInteger(int radix) { 2511 setRadix(radix); 2512 boolean result = hasNext(integerPattern()); 2513 if (result) { // Cache it 2514 try { 2515 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? 2516 processIntegerToken(hasNextResult) : 2517 hasNextResult; 2518 typeCache = new BigInteger(s, radix); 2519 } catch (NumberFormatException nfe) { 2520 result = false; 2521 } 2522 } 2523 return result; 2524 } 2525 2526 /** 2527 * Scans the next token of the input as a {@link java.math.BigInteger 2528 * BigInteger}. 2529 * 2530 * <p> An invocation of this method of the form 2531 * <tt>nextBigInteger()</tt> behaves in exactly the same way as the 2532 * invocation <tt>nextBigInteger(radix)</tt>, where <code>radix</code> 2533 * is the default radix of this scanner. 2534 * 2535 * @return the <tt>BigInteger</tt> scanned from the input 2536 * @throws InputMismatchException 2537 * if the next token does not match the <i>Integer</i> 2538 * regular expression, or is out of range 2539 * @throws NoSuchElementException if the input is exhausted 2540 * @throws IllegalStateException if this scanner is closed 2541 */ 2542 public BigInteger nextBigInteger() { 2543 return nextBigInteger(defaultRadix); 2544 } 2545 2546 /** 2547 * Scans the next token of the input as a {@link java.math.BigInteger 2548 * BigInteger}. 2549 * 2550 * <p> If the next token matches the <a 2551 * href="#Integer-regex"><i>Integer</i></a> regular expression defined 2552 * above then the token is converted into a <tt>BigInteger</tt> value as if 2553 * by removing all group separators, mapping non-ASCII digits into ASCII 2554 * digits via the {@link Character#digit Character.digit}, and passing the 2555 * resulting string to the {@link 2556 * java.math.BigInteger#BigInteger(java.lang.String) 2557 * BigInteger(String, int)} constructor with the specified radix. 2558 * 2559 * @param radix the radix used to interpret the token 2560 * @return the <tt>BigInteger</tt> scanned from the input 2561 * @throws InputMismatchException 2562 * if the next token does not match the <i>Integer</i> 2563 * regular expression, or is out of range 2564 * @throws NoSuchElementException if the input is exhausted 2565 * @throws IllegalStateException if this scanner is closed 2566 */ 2567 public BigInteger nextBigInteger(int radix) { 2568 // Check cached result 2569 if ((typeCache != null) && (typeCache instanceof BigInteger) 2570 && this.radix == radix) { 2571 BigInteger val = (BigInteger)typeCache; 2572 useTypeCache(); 2573 return val; 2574 } 2575 setRadix(radix); 2576 clearCaches(); 2577 // Search for next int 2578 try { 2579 String s = next(integerPattern()); 2580 if (matcher.group(SIMPLE_GROUP_INDEX) == null) 2581 s = processIntegerToken(s); 2582 return new BigInteger(s, radix); 2583 } catch (NumberFormatException nfe) { 2584 position = matcher.start(); // don't skip bad token 2585 throw new InputMismatchException(nfe.getMessage()); 2586 } 2587 } 2588 2589 /** 2590 * Returns true if the next token in this scanner's input can be 2591 * interpreted as a <code>BigDecimal</code> using the 2592 * {@link #nextBigDecimal} method. The scanner does not advance past any 2593 * input. 2594 * 2595 * @return true if and only if this scanner's next token is a valid 2596 * <code>BigDecimal</code> 2597 * @throws IllegalStateException if this scanner is closed 2598 */ 2599 public boolean hasNextBigDecimal() { 2600 setRadix(10); 2601 boolean result = hasNext(decimalPattern()); 2602 if (result) { // Cache it 2603 try { 2604 String s = processFloatToken(hasNextResult); 2605 typeCache = new BigDecimal(s); 2606 } catch (NumberFormatException nfe) { 2607 result = false; 2608 } 2609 } 2610 return result; 2611 } 2612 2613 /** 2614 * Scans the next token of the input as a {@link java.math.BigDecimal 2615 * BigDecimal}. 2616 * 2617 * <p> If the next token matches the <a 2618 * href="#Decimal-regex"><i>Decimal</i></a> regular expression defined 2619 * above then the token is converted into a <tt>BigDecimal</tt> value as if 2620 * by removing all group separators, mapping non-ASCII digits into ASCII 2621 * digits via the {@link Character#digit Character.digit}, and passing the 2622 * resulting string to the {@link 2623 * java.math.BigDecimal#BigDecimal(java.lang.String) BigDecimal(String)} 2624 * constructor. 2625 * 2626 * @return the <tt>BigDecimal</tt> scanned from the input 2627 * @throws InputMismatchException 2628 * if the next token does not match the <i>Decimal</i> 2629 * regular expression, or is out of range 2630 * @throws NoSuchElementException if the input is exhausted 2631 * @throws IllegalStateException if this scanner is closed 2632 */ 2633 public BigDecimal nextBigDecimal() { 2634 // Check cached result 2635 if ((typeCache != null) && (typeCache instanceof BigDecimal)) { 2636 BigDecimal val = (BigDecimal)typeCache; 2637 useTypeCache(); 2638 return val; 2639 } 2640 setRadix(10); 2641 clearCaches(); 2642 // Search for next float 2643 try { 2644 String s = processFloatToken(next(decimalPattern())); 2645 return new BigDecimal(s); 2646 } catch (NumberFormatException nfe) { 2647 position = matcher.start(); // don't skip bad token 2648 throw new InputMismatchException(nfe.getMessage()); 2649 } 2650 } 2651 2652 /** 2653 * Resets this scanner. 2654 * 2655 * <p> Resetting a scanner discards all of its explicit state 2656 * information which may have been changed by invocations of {@link 2657 * #useDelimiter}, {@link #useLocale}, or {@link #useRadix}. 2658 * 2659 * <p> An invocation of this method of the form 2660 * <tt>scanner.reset()</tt> behaves in exactly the same way as the 2661 * invocation 2662 * 2663 * <blockquote><pre> 2664 * scanner.useDelimiter("\\p{javaWhitespace}+") 2665 * .useLocale(Locale.getDefault()) 2666 * .useRadix(10); 2667 * </pre></blockquote> 2668 * 2669 * @return this scanner 2670 * 2671 * @since 1.6 2672 */ 2673 public Scanner reset() { 2674 delimPattern = WHITESPACE_PATTERN; 2675 useLocale(Locale.getDefault(Locale.Category.FORMAT)); 2676 useRadix(10); 2677 clearCaches(); 2678 return this; 2679 } 2680} 2681