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