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