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:
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 * <h3> <a name="localized-numbers">Localized numbers</a> </h3>
153 *
154 * <p> An instance of this class is capable of scanning numbers in the standard
155 * formats as well as in the formats of the scanner's locale. A scanner's
156 * <a name="initial-locale">initial locale </a>is the value returned by the {@link
157 * java.util.Locale#getDefault(Locale.Category)
158 * Locale.getDefault(Locale.Category.FORMAT)} method; it may be changed via the {@link
159 * #useLocale} method. The {@link #reset} method will reset the value of the
160 * scanner's locale to the initial locale regardless of whether it was
161 * previously changed.
162 *
163 * <p>The localized formats are defined in terms of the following parameters,
164 * which for a particular locale are taken from that locale's {@link
165 * java.text.DecimalFormat DecimalFormat} object, <tt>df</tt>, and its and
166 * {@link java.text.DecimalFormatSymbols DecimalFormatSymbols} object,
167 * <tt>dfs</tt>.
168 *
169 * <blockquote><dl>
170 * <dt><i>LocalGroupSeparator </i>
171 * <dd>The character used to separate thousands groups,
172 * <i>i.e.,</i> <tt>dfs.</tt>{@link
173 * java.text.DecimalFormatSymbols#getGroupingSeparator
174 * getGroupingSeparator()}
175 * <dt><i>LocalDecimalSeparator </i>
176 * <dd>The character used for the decimal point,
177 * <i>i.e.,</i> <tt>dfs.</tt>{@link
178 * java.text.DecimalFormatSymbols#getDecimalSeparator
179 * getDecimalSeparator()}
180 * <dt><i>LocalPositivePrefix </i>
181 * <dd>The string that appears before a positive number (may
182 * be empty), <i>i.e.,</i> <tt>df.</tt>{@link
183 * java.text.DecimalFormat#getPositivePrefix
184 * getPositivePrefix()}
185 * <dt><i>LocalPositiveSuffix </i>
186 * <dd>The string that appears after a positive number (may be
187 * empty), <i>i.e.,</i> <tt>df.</tt>{@link
188 * java.text.DecimalFormat#getPositiveSuffix
189 * getPositiveSuffix()}
190 * <dt><i>LocalNegativePrefix </i>
191 * <dd>The string that appears before a negative number (may
192 * be empty), <i>i.e.,</i> <tt>df.</tt>{@link
193 * java.text.DecimalFormat#getNegativePrefix
194 * getNegativePrefix()}
195 * <dt><i>LocalNegativeSuffix </i>
196 * <dd>The string that appears after a negative number (may be
197 * empty), <i>i.e.,</i> <tt>df.</tt>{@link
198 * java.text.DecimalFormat#getNegativeSuffix
199 * getNegativeSuffix()}
200 * <dt><i>LocalNaN </i>
201 * <dd>The string that represents not-a-number for
202 * floating-point values,
203 * <i>i.e.,</i> <tt>dfs.</tt>{@link
204 * java.text.DecimalFormatSymbols#getNaN
205 * getNaN()}
206 * <dt><i>LocalInfinity </i>
207 * <dd>The string that represents infinity for floating-point
208 * values, <i>i.e.,</i> <tt>dfs.</tt>{@link
209 * java.text.DecimalFormatSymbols#getInfinity
210 * getInfinity()}
211 * </dl></blockquote>
212 *
213 * <h4> <a name="number-syntax">Number syntax</a> </h4>
214 *
215 * <p> The strings that can be parsed as numbers by an instance of this class
216 * are specified in terms of the following regular-expression grammar, where
217 * Rmax is the highest digit in the radix being used (for example, Rmax is 9 in base 10).
218 *
219 * <dl>
220 * <dt><i>NonAsciiDigit</i>:
221 * <dd>A non-ASCII character c for which
222 * {@link java.lang.Character#isDigit Character.isDigit}<tt>(c)</tt>
223 * returns true
224 *
225 * <dt><i>Non0Digit</i>:
226 * <dd><tt>[1-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i>
227 *
228 * <dt><i>Digit</i>:
229 * <dd><tt>[0-</tt><i>Rmax</i><tt>] | </tt><i>NonASCIIDigit</i>
230 *
231 * <dt><i>GroupedNumeral</i>:
232 * <dd><tt>( </tt><i>Non0Digit</i>
233 * <i>Digit</i><tt>?
234 * </tt><i>Digit</i><tt>?</tt>
235 * <dd> <tt>( </tt><i>LocalGroupSeparator</i>
236 * <i>Digit</i>
237 * <i>Digit</i>
238 * <i>Digit</i><tt> )+ )</tt>
239 *
240 * <dt><i>Numeral</i>:
241 * <dd><tt>( ( </tt><i>Digit</i><tt>+ )
242 * | </tt><i>GroupedNumeral</i><tt> )</tt>
243 *
244 * <dt><a name="Integer-regex"><i>Integer</i>:</a>
245 * <dd><tt>( [-+]? ( </tt><i>Numeral</i><tt>
246 * ) )</tt>
247 * <dd><tt>| </tt><i>LocalPositivePrefix</i> <i>Numeral</i>
248 * <i>LocalPositiveSuffix</i>
249 * <dd><tt>| </tt><i>LocalNegativePrefix</i> <i>Numeral</i>
250 * <i>LocalNegativeSuffix</i>
251 *
252 * <dt><i>DecimalNumeral</i>:
253 * <dd><i>Numeral</i>
254 * <dd><tt>| </tt><i>Numeral</i>
255 * <i>LocalDecimalSeparator</i>
256 * <i>Digit</i><tt>*</tt>
257 * <dd><tt>| </tt><i>LocalDecimalSeparator</i>
258 * <i>Digit</i><tt>+</tt>
259 *
260 * <dt><i>Exponent</i>:
261 * <dd><tt>( [eE] [+-]? </tt><i>Digit</i><tt>+ )</tt>
262 *
263 * <dt><a name="Decimal-regex"><i>Decimal</i>:</a>
264 * <dd><tt>( [-+]? </tt><i>DecimalNumeral</i>
265 * <i>Exponent</i><tt>? )</tt>
266 * <dd><tt>| </tt><i>LocalPositivePrefix</i>
267 * <i>DecimalNumeral</i>
268 * <i>LocalPositiveSuffix</i>
269 * <i>Exponent</i><tt>?</tt>
270 * <dd><tt>| </tt><i>LocalNegativePrefix</i>
271 * <i>DecimalNumeral</i>
272 * <i>LocalNegativeSuffix</i>
273 * <i>Exponent</i><tt>?</tt>
274 *
275 * <dt><i>HexFloat</i>:
276 * <dd><tt>[-+]? 0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+
277 * ([pP][-+]?[0-9]+)?</tt>
278 *
279 * <dt><i>NonNumber</i>:
280 * <dd><tt>NaN
281 * | </tt><i>LocalNan</i><tt>
282 * | Infinity
283 * | </tt><i>LocalInfinity</i>
284 *
285 * <dt><i>SignedNonNumber</i>:
286 * <dd><tt>( [-+]? </tt><i>NonNumber</i><tt> )</tt>
287 * <dd><tt>| </tt><i>LocalPositivePrefix</i>
288 * <i>NonNumber</i>
289 * <i>LocalPositiveSuffix</i>
290 * <dd><tt>| </tt><i>LocalNegativePrefix</i>
291 * <i>NonNumber</i>
292 * <i>LocalNegativeSuffix</i>
293 *
294 * <dt><a name="Float-regex"><i>Float</i></a>:
295 * <dd><i>Decimal</i>
296 * <tt>| </tt><i>HexFloat</i>
297 * <tt>| </tt><i>SignedNonNumber</i>
298 *
299 * </dl>
300 * <p>Whitespace is not significant in the above regular expressions.
301 *
302 * @since 1.5
303 */
304 public final class Scanner implements Iterator<String>, Closeable {
305
306 // Internal buffer used to hold input
307 private CharBuffer buf;
308
309 // Size of internal character buffer
310 private static final int BUFFER_SIZE = 1024; // change to 1024;
311
312 // The index into the buffer currently held by the Scanner
313 private int position;
314
315 // Internal matcher used for finding delimiters
316 private Matcher matcher;
317
504 floatPattern = Pattern.compile(decimal + "|" + hexFloat + "|" +
505 signedNonNumber);
506 decimalPattern = Pattern.compile(decimal);
507 }
508 private Pattern floatPattern() {
509 if (floatPattern == null) {
510 buildFloatAndDecimalPattern();
511 }
512 return floatPattern;
513 }
514 private Pattern decimalPattern() {
515 if (decimalPattern == null) {
516 buildFloatAndDecimalPattern();
517 }
518 return decimalPattern;
519 }
520
521 // Constructors
522
523 /**
524 * Constructs a <code>Scanner</code> that returns values scanned
525 * from the specified source delimited by the specified pattern.
526 *
527 * @param source A character source implementing the Readable interface
528 * @param pattern A delimiting pattern
529 */
530 private Scanner(Readable source, Pattern pattern) {
531 assert source != null : "source should not be null";
532 assert pattern != null : "pattern should not be null";
533 this.source = source;
534 delimPattern = pattern;
535 buf = CharBuffer.allocate(BUFFER_SIZE);
536 buf.limit(0);
537 matcher = delimPattern.matcher(buf);
538 matcher.useTransparentBounds(true);
539 matcher.useAnchoringBounds(false);
540 useLocale(Locale.getDefault(Locale.Category.FORMAT));
541 }
542
543 /**
544 * Constructs a new <code>Scanner</code> that produces values scanned
545 * from the specified source.
546 *
547 * @param source A character source implementing the {@link Readable}
548 * interface
549 */
550 public Scanner(Readable source) {
551 this(Objects.requireNonNull(source, "source"), WHITESPACE_PATTERN);
552 }
553
554 /**
555 * Constructs a new <code>Scanner</code> that produces values scanned
556 * from the specified input stream. Bytes from the stream are converted
557 * into characters using the underlying platform's
558 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
559 *
560 * @param source An input stream to be scanned
561 */
562 public Scanner(InputStream source) {
563 this(new InputStreamReader(source), WHITESPACE_PATTERN);
564 }
565
566 /**
567 * Constructs a new <code>Scanner</code> that produces values scanned
568 * from the specified input stream. Bytes from the stream are converted
569 * into characters using the specified charset.
570 *
571 * @param source An input stream to be scanned
572 * @param charsetName The encoding type used to convert bytes from the
573 * stream into characters to be scanned
574 * @throws IllegalArgumentException if the specified character set
575 * does not exist
576 */
577 public Scanner(InputStream source, String charsetName) {
578 this(makeReadable(Objects.requireNonNull(source, "source"), toCharset(charsetName)),
579 WHITESPACE_PATTERN);
580 }
581
582 /**
583 * Returns a charset object for the given charset name.
584 * @throws NullPointerException is csn is null
585 * @throws IllegalArgumentException if the charset is not supported
586 */
587 private static Charset toCharset(String csn) {
588 Objects.requireNonNull(csn, "charsetName");
589 try {
590 return Charset.forName(csn);
591 } catch (IllegalCharsetNameException|UnsupportedCharsetException e) {
592 // IllegalArgumentException should be thrown
593 throw new IllegalArgumentException(e);
594 }
595 }
596
597 private static Readable makeReadable(InputStream source, Charset charset) {
598 return new InputStreamReader(source, charset);
599 }
600
601 /**
602 * Constructs a new <code>Scanner</code> that produces values scanned
603 * from the specified file. Bytes from the file are converted into
604 * characters using the underlying platform's
605 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
606 *
607 * @param source A file to be scanned
608 * @throws FileNotFoundException if source is not found
609 */
610 public Scanner(File source) throws FileNotFoundException {
611 this((ReadableByteChannel)(new FileInputStream(source).getChannel()));
612 }
613
614 /**
615 * Constructs a new <code>Scanner</code> that produces values scanned
616 * from the specified file. Bytes from the file are converted into
617 * characters using the specified charset.
618 *
619 * @param source A file to be scanned
620 * @param charsetName The encoding type used to convert bytes from the file
621 * into characters to be scanned
622 * @throws FileNotFoundException if source is not found
623 * @throws IllegalArgumentException if the specified encoding is
624 * not found
625 */
626 public Scanner(File source, String charsetName)
627 throws FileNotFoundException
628 {
629 this(Objects.requireNonNull(source), toDecoder(charsetName));
630 }
631
632 private Scanner(File source, CharsetDecoder dec)
633 throws FileNotFoundException
634 {
635 this(makeReadable((ReadableByteChannel)(new FileInputStream(source).getChannel()), dec));
636 }
637
638 private static CharsetDecoder toDecoder(String charsetName) {
639 Objects.requireNonNull(charsetName, "charsetName");
640 try {
641 return Charset.forName(charsetName).newDecoder();
642 } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {
643 throw new IllegalArgumentException(charsetName);
644 }
645 }
646
647 private static Readable makeReadable(ReadableByteChannel source,
648 CharsetDecoder dec) {
649 return Channels.newReader(source, dec, -1);
650 }
651
652 /**
653 * Constructs a new <code>Scanner</code> that produces values scanned
654 * from the specified file. Bytes from the file are converted into
655 * characters using the underlying platform's
656 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
657 *
658 * @param source
659 * the path to the file to be scanned
660 * @throws IOException
661 * if an I/O error occurs opening source
662 *
663 * @since 1.7
664 */
665 public Scanner(Path source)
666 throws IOException
667 {
668 this(Files.newInputStream(source));
669 }
670
671 /**
672 * Constructs a new <code>Scanner</code> that produces values scanned
673 * from the specified file. Bytes from the file are converted into
674 * characters using the specified charset.
675 *
676 * @param source
677 * the path to the file to be scanned
678 * @param charsetName
679 * The encoding type used to convert bytes from the file
680 * into characters to be scanned
681 * @throws IOException
682 * if an I/O error occurs opening source
683 * @throws IllegalArgumentException
684 * if the specified encoding is not found
685 * @since 1.7
686 */
687 public Scanner(Path source, String charsetName) throws IOException {
688 this(Objects.requireNonNull(source), toCharset(charsetName));
689 }
690
691 private Scanner(Path source, Charset charset) throws IOException {
692 this(makeReadable(Files.newInputStream(source), charset));
693 }
694
695 /**
696 * Constructs a new <code>Scanner</code> that produces values scanned
697 * from the specified string.
698 *
699 * @param source A string to scan
700 */
701 public Scanner(String source) {
702 this(new StringReader(source), WHITESPACE_PATTERN);
703 }
704
705 /**
706 * Constructs a new <code>Scanner</code> that produces values scanned
707 * from the specified channel. Bytes from the source are converted into
708 * characters using the underlying platform's
709 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
710 *
711 * @param source A channel to scan
712 */
713 public Scanner(ReadableByteChannel source) {
714 this(makeReadable(Objects.requireNonNull(source, "source")),
715 WHITESPACE_PATTERN);
716 }
717
718 private static Readable makeReadable(ReadableByteChannel source) {
719 return makeReadable(source, Charset.defaultCharset().newDecoder());
720 }
721
722 /**
723 * Constructs a new <code>Scanner</code> that produces values scanned
724 * from the specified channel. Bytes from the source are converted into
725 * characters using the specified charset.
726 *
727 * @param source A channel to scan
728 * @param charsetName The encoding type used to convert bytes from the
729 * channel into characters to be scanned
730 * @throws IllegalArgumentException if the specified character set
731 * does not exist
732 */
733 public Scanner(ReadableByteChannel source, String charsetName) {
734 this(makeReadable(Objects.requireNonNull(source, "source"), toDecoder(charsetName)),
735 WHITESPACE_PATTERN);
736 }
737
738 // Private primitives used to support scanning
739
740 private void saveState() {
741 savedScannerPosition = position;
742 }
743
1060 return null;
1061
1062 // Read more to find pattern
1063 needInput = true;
1064 return null;
1065 }
1066
1067 // Throws if the scanner is closed
1068 private void ensureOpen() {
1069 if (closed)
1070 throw new IllegalStateException("Scanner closed");
1071 }
1072
1073 // Public methods
1074
1075 /**
1076 * Closes this scanner.
1077 *
1078 * <p> If this scanner has not yet been closed then if its underlying
1079 * {@linkplain java.lang.Readable readable} also implements the {@link
1080 * java.io.Closeable} interface then the readable's <tt>close</tt> method
1081 * will be invoked. If this scanner is already closed then invoking this
1082 * method will have no effect.
1083 *
1084 * <p>Attempting to perform search operations after a scanner has
1085 * been closed will result in an {@link IllegalStateException}.
1086 *
1087 */
1088 public void close() {
1089 if (closed)
1090 return;
1091 if (source instanceof Closeable) {
1092 try {
1093 ((Closeable)source).close();
1094 } catch (IOException ioe) {
1095 lastException = ioe;
1096 }
1097 }
1098 sourceClosed = true;
1099 source = null;
1100 closed = true;
1101 }
1102
1103 /**
1104 * Returns the <code>IOException</code> last thrown by this
1105 * <code>Scanner</code>'s underlying <code>Readable</code>. This method
1106 * returns <code>null</code> if no such exception exists.
1107 *
1108 * @return the last exception thrown by this scanner's readable
1109 */
1110 public IOException ioException() {
1111 return lastException;
1112 }
1113
1114 /**
1115 * Returns the <code>Pattern</code> this <code>Scanner</code> is currently
1116 * using to match delimiters.
1117 *
1118 * @return this scanner's delimiting pattern.
1119 */
1120 public Pattern delimiter() {
1121 return delimPattern;
1122 }
1123
1124 /**
1125 * Sets this scanner's delimiting pattern to the specified pattern.
1126 *
1127 * @param pattern A delimiting pattern
1128 * @return this scanner
1129 */
1130 public Scanner useDelimiter(Pattern pattern) {
1131 delimPattern = pattern;
1132 return this;
1133 }
1134
1135 /**
1136 * Sets this scanner's delimiting pattern to a pattern constructed from
1137 * the specified <code>String</code>.
1138 *
1139 * <p> An invocation of this method of the form
1140 * <tt>useDelimiter(pattern)</tt> behaves in exactly the same way as the
1141 * invocation <tt>useDelimiter(Pattern.compile(pattern))</tt>.
1142 *
1143 * <p> Invoking the {@link #reset} method will set the scanner's delimiter
1144 * to the <a href= "#default-delimiter">default</a>.
1145 *
1146 * @param pattern A string specifying a delimiting pattern
1147 * @return this scanner
1148 */
1149 public Scanner useDelimiter(String pattern) {
1150 delimPattern = patternCache.forName(pattern);
1151 return this;
1152 }
1153
1154 /**
1155 * Returns this scanner's locale.
1156 *
1157 * <p>A scanner's locale affects many elements of its default
1158 * primitive matching regular expressions; see
1159 * <a href= "#localized-numbers">localized numbers</a> above.
1160 *
1161 * @return this scanner's locale
1219 /**
1220 * Returns this scanner's default radix.
1221 *
1222 * <p>A scanner's radix affects elements of its default
1223 * number matching regular expressions; see
1224 * <a href= "#localized-numbers">localized numbers</a> above.
1225 *
1226 * @return the default radix of this scanner
1227 */
1228 public int radix() {
1229 return this.defaultRadix;
1230 }
1231
1232 /**
1233 * Sets this scanner's default radix to the specified radix.
1234 *
1235 * <p>A scanner's radix affects elements of its default
1236 * number matching regular expressions; see
1237 * <a href= "#localized-numbers">localized numbers</a> above.
1238 *
1239 * <p>If the radix is less than <code>Character.MIN_RADIX</code>
1240 * or greater than <code>Character.MAX_RADIX</code>, then an
1241 * <code>IllegalArgumentException</code> is thrown.
1242 *
1243 * <p>Invoking the {@link #reset} method will set the scanner's radix to
1244 * <code>10</code>.
1245 *
1246 * @param radix The radix to use when scanning numbers
1247 * @return this scanner
1248 * @throws IllegalArgumentException if radix is out of range
1249 */
1250 public Scanner useRadix(int radix) {
1251 if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX))
1252 throw new IllegalArgumentException("radix:"+radix);
1253
1254 if (this.defaultRadix == radix)
1255 return this;
1256 this.defaultRadix = radix;
1257 // Force rebuilding and recompilation of radix dependent patterns
1258 integerPattern = null;
1259 return this;
1260 }
1261
1262 // The next operation should occur in the specified radix but
1263 // the default is left untouched.
1264 private void setRadix(int radix) {
1265 if (this.radix != radix) {
1266 // Force rebuilding and recompilation of radix dependent patterns
1267 integerPattern = null;
1268 this.radix = radix;
1269 }
1270 }
1271
1272 /**
1273 * Returns the match result of the last scanning operation performed
1274 * by this scanner. This method throws <code>IllegalStateException</code>
1275 * if no match has been performed, or if the last match was
1276 * not successful.
1277 *
1278 * <p>The various <code>next</code>methods of <code>Scanner</code>
1279 * make a match result available if they complete without throwing an
1280 * exception. For instance, after an invocation of the {@link #nextInt}
1281 * method that returned an int, this method returns a
1282 * <code>MatchResult</code> for the search of the
1283 * <a href="#Integer-regex"><i>Integer</i></a> regular expression
1284 * defined above. Similarly the {@link #findInLine},
1285 * {@link #findWithinHorizon}, and {@link #skip} methods will make a
1286 * match available if they succeed.
1287 *
1288 * @return a match result for the last match operation
1289 * @throws IllegalStateException If no match result is available
1290 */
1291 public MatchResult match() {
1292 if (!matchValid)
1293 throw new IllegalStateException("No match result available");
1294 return matcher.toMatchResult();
1295 }
1296
1297 /**
1298 * <p>Returns the string representation of this <code>Scanner</code>. The
1299 * string representation of a <code>Scanner</code> contains information
1300 * that may be useful for debugging. The exact format is unspecified.
1301 *
1302 * @return The string representation of this scanner
1303 */
1304 public String toString() {
1305 StringBuilder sb = new StringBuilder();
1306 sb.append("java.util.Scanner");
1307 sb.append("[delimiters=" + delimPattern + "]");
1308 sb.append("[position=" + position + "]");
1309 sb.append("[match valid=" + matchValid + "]");
1310 sb.append("[need input=" + needInput + "]");
1311 sb.append("[source closed=" + sourceClosed + "]");
1312 sb.append("[skipped=" + skipped + "]");
1313 sb.append("[group separator=" + groupSeparator + "]");
1314 sb.append("[decimal separator=" + decimalSeparator + "]");
1315 sb.append("[positive prefix=" + positivePrefix + "]");
1316 sb.append("[negative prefix=" + negativePrefix + "]");
1317 sb.append("[positive suffix=" + positiveSuffix + "]");
1318 sb.append("[negative suffix=" + negativeSuffix + "]");
1319 sb.append("[NaN string=" + nanString + "]");
1330 * @throws IllegalStateException if this scanner is closed
1331 * @see java.util.Iterator
1332 */
1333 public boolean hasNext() {
1334 ensureOpen();
1335 saveState();
1336 while (!sourceClosed) {
1337 if (hasTokenInBuffer())
1338 return revertState(true);
1339 readInput();
1340 }
1341 boolean result = hasTokenInBuffer();
1342 return revertState(result);
1343 }
1344
1345 /**
1346 * Finds and returns the next complete token from this scanner.
1347 * A complete token is preceded and followed by input that matches
1348 * the delimiter pattern. This method may block while waiting for input
1349 * to scan, even if a previous invocation of {@link #hasNext} returned
1350 * <code>true</code>.
1351 *
1352 * @return the next token
1353 * @throws NoSuchElementException if no more tokens are available
1354 * @throws IllegalStateException if this scanner is closed
1355 * @see java.util.Iterator
1356 */
1357 public String next() {
1358 ensureOpen();
1359 clearCaches();
1360
1361 while (true) {
1362 String token = getCompleteTokenInBuffer(null);
1363 if (token != null) {
1364 matchValid = true;
1365 skipped = false;
1366 return token;
1367 }
1368 if (needInput)
1369 readInput();
1370 else
1371 throwFor();
1372 }
1373 }
1374
1375 /**
1376 * The remove operation is not supported by this implementation of
1377 * <code>Iterator</code>.
1378 *
1379 * @throws UnsupportedOperationException if this method is invoked.
1380 * @see java.util.Iterator
1381 */
1382 public void remove() {
1383 throw new UnsupportedOperationException();
1384 }
1385
1386 /**
1387 * Returns true if the next token matches the pattern constructed from the
1388 * specified string. The scanner does not advance past any input.
1389 *
1390 * <p> An invocation of this method of the form <tt>hasNext(pattern)</tt>
1391 * behaves in exactly the same way as the invocation
1392 * <tt>hasNext(Pattern.compile(pattern))</tt>.
1393 *
1394 * @param pattern a string specifying the pattern to scan
1395 * @return true if and only if this scanner has another token matching
1396 * the specified pattern
1397 * @throws IllegalStateException if this scanner is closed
1398 */
1399 public boolean hasNext(String pattern) {
1400 return hasNext(patternCache.forName(pattern));
1401 }
1402
1403 /**
1404 * Returns the next token if it matches the pattern constructed from the
1405 * specified string. If the match is successful, the scanner advances
1406 * past the input that matched the pattern.
1407 *
1408 * <p> An invocation of this method of the form <tt>next(pattern)</tt>
1409 * behaves in exactly the same way as the invocation
1410 * <tt>next(Pattern.compile(pattern))</tt>.
1411 *
1412 * @param pattern a string specifying the pattern to scan
1413 * @return the next token
1414 * @throws NoSuchElementException if no such tokens are available
1415 * @throws IllegalStateException if this scanner is closed
1416 */
1417 public String next(String pattern) {
1418 return next(patternCache.forName(pattern));
1419 }
1420
1421 /**
1422 * Returns true if the next complete token matches the specified pattern.
1423 * A complete token is prefixed and postfixed by input that matches
1424 * the delimiter pattern. This method may block while waiting for input.
1425 * The scanner does not advance past any input.
1426 *
1427 * @param pattern the pattern to scan for
1428 * @return true if and only if this scanner has another token matching
1429 * the specified pattern
1430 * @throws IllegalStateException if this scanner is closed
1435 throw new NullPointerException();
1436 hasNextPattern = null;
1437 saveState();
1438
1439 while (true) {
1440 if (getCompleteTokenInBuffer(pattern) != null) {
1441 matchValid = true;
1442 cacheResult();
1443 return revertState(true);
1444 }
1445 if (needInput)
1446 readInput();
1447 else
1448 return revertState(false);
1449 }
1450 }
1451
1452 /**
1453 * Returns the next token if it matches the specified pattern. This
1454 * method may block while waiting for input to scan, even if a previous
1455 * invocation of {@link #hasNext(Pattern)} returned <code>true</code>.
1456 * If the match is successful, the scanner advances past the input that
1457 * matched the pattern.
1458 *
1459 * @param pattern the pattern to scan for
1460 * @return the next token
1461 * @throws NoSuchElementException if no more tokens are available
1462 * @throws IllegalStateException if this scanner is closed
1463 */
1464 public String next(Pattern pattern) {
1465 ensureOpen();
1466 if (pattern == null)
1467 throw new NullPointerException();
1468
1469 // Did we already find this pattern?
1470 if (hasNextPattern == pattern)
1471 return getCachedResult();
1472 clearCaches();
1473
1474 // Search for the pattern
1475 while (true) {
1537
1538 String result = findWithinHorizon(linePattern, 0);
1539 if (result == null)
1540 throw new NoSuchElementException("No line found");
1541 MatchResult mr = this.match();
1542 String lineSep = mr.group(1);
1543 if (lineSep != null)
1544 result = result.substring(0, result.length() - lineSep.length());
1545 if (result == null)
1546 throw new NoSuchElementException();
1547 else
1548 return result;
1549 }
1550
1551 // Public methods that ignore delimiters
1552
1553 /**
1554 * Attempts to find the next occurrence of a pattern constructed from the
1555 * specified string, ignoring delimiters.
1556 *
1557 * <p>An invocation of this method of the form <tt>findInLine(pattern)</tt>
1558 * behaves in exactly the same way as the invocation
1559 * <tt>findInLine(Pattern.compile(pattern))</tt>.
1560 *
1561 * @param pattern a string specifying the pattern to search for
1562 * @return the text that matched the specified pattern
1563 * @throws IllegalStateException if this scanner is closed
1564 */
1565 public String findInLine(String pattern) {
1566 return findInLine(patternCache.forName(pattern));
1567 }
1568
1569 /**
1570 * Attempts to find the next occurrence of the specified pattern ignoring
1571 * delimiters. If the pattern is found before the next line separator, the
1572 * scanner advances past the input that matched and returns the string that
1573 * matched the pattern.
1574 * If no such pattern is detected in the input up to the next line
1575 * separator, then <code>null</code> is returned and the scanner's
1576 * position is unchanged. This method may block waiting for input that
1577 * matches the pattern.
1578 *
1579 * <p>Since this method continues to search through the input looking
1580 * for the specified pattern, it may buffer all of the input searching for
1581 * the desired token if no line separators are present.
1582 *
1583 * @param pattern the pattern to scan for
1584 * @return the text that matched the specified pattern
1585 * @throws IllegalStateException if this scanner is closed
1586 */
1587 public String findInLine(Pattern pattern) {
1588 ensureOpen();
1589 if (pattern == null)
1590 throw new NullPointerException();
1591 clearCaches();
1592 // Expand buffer to include the next newline or end of input
1593 int endPosition = 0;
1594 saveState();
1595 while (true) {
1604 endPosition = buf.limit();
1605 break; // up to end of input
1606 }
1607 }
1608 revertState();
1609 int horizonForLine = endPosition - position;
1610 // If there is nothing between the current pos and the next
1611 // newline simply return null, invoking findWithinHorizon
1612 // with "horizon=0" will scan beyond the line bound.
1613 if (horizonForLine == 0)
1614 return null;
1615 // Search for the pattern
1616 return findWithinHorizon(pattern, horizonForLine);
1617 }
1618
1619 /**
1620 * Attempts to find the next occurrence of a pattern constructed from the
1621 * specified string, ignoring delimiters.
1622 *
1623 * <p>An invocation of this method of the form
1624 * <tt>findWithinHorizon(pattern)</tt> behaves in exactly the same way as
1625 * the invocation
1626 * <tt>findWithinHorizon(Pattern.compile(pattern, horizon))</tt>.
1627 *
1628 * @param pattern a string specifying the pattern to search for
1629 * @param horizon the search horizon
1630 * @return the text that matched the specified pattern
1631 * @throws IllegalStateException if this scanner is closed
1632 * @throws IllegalArgumentException if horizon is negative
1633 */
1634 public String findWithinHorizon(String pattern, int horizon) {
1635 return findWithinHorizon(patternCache.forName(pattern), horizon);
1636 }
1637
1638 /**
1639 * Attempts to find the next occurrence of the specified pattern.
1640 *
1641 * <p>This method searches through the input up to the specified
1642 * search horizon, ignoring delimiters. If the pattern is found the
1643 * scanner advances past the input that matched and returns the string
1644 * that matched the pattern. If no such pattern is detected then the
1645 * null is returned and the scanner's position remains unchanged. This
1646 * method may block waiting for input that matches the pattern.
1647 *
1648 * <p>A scanner will never search more than <code>horizon</code> code
1649 * points beyond its current position. Note that a match may be clipped
1650 * by the horizon; that is, an arbitrary match result may have been
1651 * different if the horizon had been larger. The scanner treats the
1652 * horizon as a transparent, non-anchoring bound (see {@link
1653 * Matcher#useTransparentBounds} and {@link Matcher#useAnchoringBounds}).
1654 *
1655 * <p>If horizon is <code>0</code>, then the horizon is ignored and
1656 * this method continues to search through the input looking for the
1657 * specified pattern without bound. In this case it may buffer all of
1658 * the input searching for the pattern.
1659 *
1660 * <p>If horizon is negative, then an IllegalArgumentException is
1661 * thrown.
1662 *
1663 * @param pattern the pattern to scan for
1664 * @param horizon the search horizon
1665 * @return the text that matched the specified pattern
1666 * @throws IllegalStateException if this scanner is closed
1667 * @throws IllegalArgumentException if horizon is negative
1668 */
1669 public String findWithinHorizon(Pattern pattern, int horizon) {
1670 ensureOpen();
1671 if (pattern == null)
1672 throw new NullPointerException();
1673 if (horizon < 0)
1674 throw new IllegalArgumentException("horizon < 0");
1675 clearCaches();
1679 String token = findPatternInBuffer(pattern, horizon);
1680 if (token != null) {
1681 matchValid = true;
1682 return token;
1683 }
1684 if (needInput)
1685 readInput();
1686 else
1687 break; // up to end of input
1688 }
1689 return null;
1690 }
1691
1692 /**
1693 * Skips input that matches the specified pattern, ignoring delimiters.
1694 * This method will skip input if an anchored match of the specified
1695 * pattern succeeds.
1696 *
1697 * <p>If a match to the specified pattern is not found at the
1698 * current position, then no input is skipped and a
1699 * <tt>NoSuchElementException</tt> is thrown.
1700 *
1701 * <p>Since this method seeks to match the specified pattern starting at
1702 * the scanner's current position, patterns that can match a lot of
1703 * input (".*", for example) may cause the scanner to buffer a large
1704 * amount of input.
1705 *
1706 * <p>Note that it is possible to skip something without risking a
1707 * <code>NoSuchElementException</code> by using a pattern that can
1708 * match nothing, e.g., <code>sc.skip("[ \t]*")</code>.
1709 *
1710 * @param pattern a string specifying the pattern to skip over
1711 * @return this scanner
1712 * @throws NoSuchElementException if the specified pattern is not found
1713 * @throws IllegalStateException if this scanner is closed
1714 */
1715 public Scanner skip(Pattern pattern) {
1716 ensureOpen();
1717 if (pattern == null)
1718 throw new NullPointerException();
1719 clearCaches();
1720
1721 // Search for the pattern
1722 while (true) {
1723 String token = matchPatternInBuffer(pattern);
1724 if (token != null) {
1725 matchValid = true;
1726 position = matcher.end();
1727 return this;
1728 }
1729 if (needInput)
1730 readInput();
1731 else
1732 throw new NoSuchElementException();
1733 }
1734 }
1735
1736 /**
1737 * Skips input that matches a pattern constructed from the specified
1738 * string.
1739 *
1740 * <p> An invocation of this method of the form <tt>skip(pattern)</tt>
1741 * behaves in exactly the same way as the invocation
1742 * <tt>skip(Pattern.compile(pattern))</tt>.
1743 *
1744 * @param pattern a string specifying the pattern to skip over
1745 * @return this scanner
1746 * @throws IllegalStateException if this scanner is closed
1747 */
1748 public Scanner skip(String pattern) {
1749 return skip(patternCache.forName(pattern));
1750 }
1751
1752 // Convenience methods for scanning primitives
1753
1754 /**
1755 * Returns true if the next token in this scanner's input can be
1756 * interpreted as a boolean value using a case insensitive pattern
1757 * created from the string "true|false". The scanner does not
1758 * advance past the input that matched.
1759 *
1760 * @return true if and only if this scanner's next token is a valid
1761 * boolean value
1762 * @throws IllegalStateException if this scanner is closed
1763 */
1764 public boolean hasNextBoolean() {
1765 return hasNext(boolPattern());
1766 }
1767
1768 /**
1769 * Scans the next token of the input into a boolean value and returns
1770 * that value. This method will throw <code>InputMismatchException</code>
1771 * if the next token cannot be translated into a valid boolean value.
1772 * If the match is successful, the scanner advances past the input that
1773 * matched.
1774 *
1775 * @return the boolean scanned from the input
1776 * @throws InputMismatchException if the next token is not a valid boolean
1777 * @throws NoSuchElementException if input is exhausted
1778 * @throws IllegalStateException if this scanner is closed
1779 */
1780 public boolean nextBoolean() {
1781 clearCaches();
1782 return Boolean.parseBoolean(next(boolPattern()));
1783 }
1784
1785 /**
1786 * Returns true if the next token in this scanner's input can be
1787 * interpreted as a byte value in the default radix using the
1788 * {@link #nextByte} method. The scanner does not advance past any input.
1789 *
1790 * @return true if and only if this scanner's next token is a valid
1805 * byte value
1806 * @throws IllegalStateException if this scanner is closed
1807 */
1808 public boolean hasNextByte(int radix) {
1809 setRadix(radix);
1810 boolean result = hasNext(integerPattern());
1811 if (result) { // Cache it
1812 try {
1813 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
1814 processIntegerToken(hasNextResult) :
1815 hasNextResult;
1816 typeCache = Byte.parseByte(s, radix);
1817 } catch (NumberFormatException nfe) {
1818 result = false;
1819 }
1820 }
1821 return result;
1822 }
1823
1824 /**
1825 * Scans the next token of the input as a <tt>byte</tt>.
1826 *
1827 * <p> An invocation of this method of the form
1828 * <tt>nextByte()</tt> behaves in exactly the same way as the
1829 * invocation <tt>nextByte(radix)</tt>, where <code>radix</code>
1830 * is the default radix of this scanner.
1831 *
1832 * @return the <tt>byte</tt> scanned from the input
1833 * @throws InputMismatchException
1834 * if the next token does not match the <i>Integer</i>
1835 * regular expression, or is out of range
1836 * @throws NoSuchElementException if input is exhausted
1837 * @throws IllegalStateException if this scanner is closed
1838 */
1839 public byte nextByte() {
1840 return nextByte(defaultRadix);
1841 }
1842
1843 /**
1844 * Scans the next token of the input as a <tt>byte</tt>.
1845 * This method will throw <code>InputMismatchException</code>
1846 * if the next token cannot be translated into a valid byte value as
1847 * described below. If the translation is successful, the scanner advances
1848 * past the input that matched.
1849 *
1850 * <p> If the next token matches the <a
1851 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
1852 * above then the token is converted into a <tt>byte</tt> value as if by
1853 * removing all locale specific prefixes, group separators, and locale
1854 * specific suffixes, then mapping non-ASCII digits into ASCII
1855 * digits via {@link Character#digit Character.digit}, prepending a
1856 * negative sign (-) if the locale specific negative prefixes and suffixes
1857 * were present, and passing the resulting string to
1858 * {@link Byte#parseByte(String, int) Byte.parseByte} with the
1859 * specified radix.
1860 *
1861 * @param radix the radix used to interpret the token as a byte value
1862 * @return the <tt>byte</tt> scanned from the input
1863 * @throws InputMismatchException
1864 * if the next token does not match the <i>Integer</i>
1865 * regular expression, or is out of range
1866 * @throws NoSuchElementException if input is exhausted
1867 * @throws IllegalStateException if this scanner is closed
1868 */
1869 public byte nextByte(int radix) {
1870 // Check cached result
1871 if ((typeCache != null) && (typeCache instanceof Byte)
1872 && this.radix == radix) {
1873 byte val = ((Byte)typeCache).byteValue();
1874 useTypeCache();
1875 return val;
1876 }
1877 setRadix(radix);
1878 clearCaches();
1879 // Search for next byte
1880 try {
1881 String s = next(integerPattern());
1882 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
1911 * short value in the specified radix
1912 * @throws IllegalStateException if this scanner is closed
1913 */
1914 public boolean hasNextShort(int radix) {
1915 setRadix(radix);
1916 boolean result = hasNext(integerPattern());
1917 if (result) { // Cache it
1918 try {
1919 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
1920 processIntegerToken(hasNextResult) :
1921 hasNextResult;
1922 typeCache = Short.parseShort(s, radix);
1923 } catch (NumberFormatException nfe) {
1924 result = false;
1925 }
1926 }
1927 return result;
1928 }
1929
1930 /**
1931 * Scans the next token of the input as a <tt>short</tt>.
1932 *
1933 * <p> An invocation of this method of the form
1934 * <tt>nextShort()</tt> behaves in exactly the same way as the
1935 * invocation <tt>nextShort(radix)</tt>, where <code>radix</code>
1936 * is the default radix of this scanner.
1937 *
1938 * @return the <tt>short</tt> scanned from the input
1939 * @throws InputMismatchException
1940 * if the next token does not match the <i>Integer</i>
1941 * regular expression, or is out of range
1942 * @throws NoSuchElementException if input is exhausted
1943 * @throws IllegalStateException if this scanner is closed
1944 */
1945 public short nextShort() {
1946 return nextShort(defaultRadix);
1947 }
1948
1949 /**
1950 * Scans the next token of the input as a <tt>short</tt>.
1951 * This method will throw <code>InputMismatchException</code>
1952 * if the next token cannot be translated into a valid short value as
1953 * described below. If the translation is successful, the scanner advances
1954 * past the input that matched.
1955 *
1956 * <p> If the next token matches the <a
1957 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
1958 * above then the token is converted into a <tt>short</tt> value as if by
1959 * removing all locale specific prefixes, group separators, and locale
1960 * specific suffixes, then mapping non-ASCII digits into ASCII
1961 * digits via {@link Character#digit Character.digit}, prepending a
1962 * negative sign (-) if the locale specific negative prefixes and suffixes
1963 * were present, and passing the resulting string to
1964 * {@link Short#parseShort(String, int) Short.parseShort} with the
1965 * specified radix.
1966 *
1967 * @param radix the radix used to interpret the token as a short value
1968 * @return the <tt>short</tt> scanned from the input
1969 * @throws InputMismatchException
1970 * if the next token does not match the <i>Integer</i>
1971 * regular expression, or is out of range
1972 * @throws NoSuchElementException if input is exhausted
1973 * @throws IllegalStateException if this scanner is closed
1974 */
1975 public short nextShort(int radix) {
1976 // Check cached result
1977 if ((typeCache != null) && (typeCache instanceof Short)
1978 && this.radix == radix) {
1979 short val = ((Short)typeCache).shortValue();
1980 useTypeCache();
1981 return val;
1982 }
1983 setRadix(radix);
1984 clearCaches();
1985 // Search for next short
1986 try {
1987 String s = next(integerPattern());
1988 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2041 private String processIntegerToken(String token) {
2042 String result = token.replaceAll(""+groupSeparator, "");
2043 boolean isNegative = false;
2044 int preLen = negativePrefix.length();
2045 if ((preLen > 0) && result.startsWith(negativePrefix)) {
2046 isNegative = true;
2047 result = result.substring(preLen);
2048 }
2049 int sufLen = negativeSuffix.length();
2050 if ((sufLen > 0) && result.endsWith(negativeSuffix)) {
2051 isNegative = true;
2052 result = result.substring(result.length() - sufLen,
2053 result.length());
2054 }
2055 if (isNegative)
2056 result = "-" + result;
2057 return result;
2058 }
2059
2060 /**
2061 * Scans the next token of the input as an <tt>int</tt>.
2062 *
2063 * <p> An invocation of this method of the form
2064 * <tt>nextInt()</tt> behaves in exactly the same way as the
2065 * invocation <tt>nextInt(radix)</tt>, where <code>radix</code>
2066 * is the default radix of this scanner.
2067 *
2068 * @return the <tt>int</tt> scanned from the input
2069 * @throws InputMismatchException
2070 * if the next token does not match the <i>Integer</i>
2071 * regular expression, or is out of range
2072 * @throws NoSuchElementException if input is exhausted
2073 * @throws IllegalStateException if this scanner is closed
2074 */
2075 public int nextInt() {
2076 return nextInt(defaultRadix);
2077 }
2078
2079 /**
2080 * Scans the next token of the input as an <tt>int</tt>.
2081 * This method will throw <code>InputMismatchException</code>
2082 * if the next token cannot be translated into a valid int value as
2083 * described below. If the translation is successful, the scanner advances
2084 * past the input that matched.
2085 *
2086 * <p> If the next token matches the <a
2087 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
2088 * above then the token is converted into an <tt>int</tt> value as if by
2089 * removing all locale specific prefixes, group separators, and locale
2090 * specific suffixes, then mapping non-ASCII digits into ASCII
2091 * digits via {@link Character#digit Character.digit}, prepending a
2092 * negative sign (-) if the locale specific negative prefixes and suffixes
2093 * were present, and passing the resulting string to
2094 * {@link Integer#parseInt(String, int) Integer.parseInt} with the
2095 * specified radix.
2096 *
2097 * @param radix the radix used to interpret the token as an int value
2098 * @return the <tt>int</tt> scanned from the input
2099 * @throws InputMismatchException
2100 * if the next token does not match the <i>Integer</i>
2101 * regular expression, or is out of range
2102 * @throws NoSuchElementException if input is exhausted
2103 * @throws IllegalStateException if this scanner is closed
2104 */
2105 public int nextInt(int radix) {
2106 // Check cached result
2107 if ((typeCache != null) && (typeCache instanceof Integer)
2108 && this.radix == radix) {
2109 int val = ((Integer)typeCache).intValue();
2110 useTypeCache();
2111 return val;
2112 }
2113 setRadix(radix);
2114 clearCaches();
2115 // Search for next int
2116 try {
2117 String s = next(integerPattern());
2118 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2147 * long value
2148 * @throws IllegalStateException if this scanner is closed
2149 */
2150 public boolean hasNextLong(int radix) {
2151 setRadix(radix);
2152 boolean result = hasNext(integerPattern());
2153 if (result) { // Cache it
2154 try {
2155 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
2156 processIntegerToken(hasNextResult) :
2157 hasNextResult;
2158 typeCache = Long.parseLong(s, radix);
2159 } catch (NumberFormatException nfe) {
2160 result = false;
2161 }
2162 }
2163 return result;
2164 }
2165
2166 /**
2167 * Scans the next token of the input as a <tt>long</tt>.
2168 *
2169 * <p> An invocation of this method of the form
2170 * <tt>nextLong()</tt> behaves in exactly the same way as the
2171 * invocation <tt>nextLong(radix)</tt>, where <code>radix</code>
2172 * is the default radix of this scanner.
2173 *
2174 * @return the <tt>long</tt> scanned from the input
2175 * @throws InputMismatchException
2176 * if the next token does not match the <i>Integer</i>
2177 * regular expression, or is out of range
2178 * @throws NoSuchElementException if input is exhausted
2179 * @throws IllegalStateException if this scanner is closed
2180 */
2181 public long nextLong() {
2182 return nextLong(defaultRadix);
2183 }
2184
2185 /**
2186 * Scans the next token of the input as a <tt>long</tt>.
2187 * This method will throw <code>InputMismatchException</code>
2188 * if the next token cannot be translated into a valid long value as
2189 * described below. If the translation is successful, the scanner advances
2190 * past the input that matched.
2191 *
2192 * <p> If the next token matches the <a
2193 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
2194 * above then the token is converted into a <tt>long</tt> value as if by
2195 * removing all locale specific prefixes, group separators, and locale
2196 * specific suffixes, then mapping non-ASCII digits into ASCII
2197 * digits via {@link Character#digit Character.digit}, prepending a
2198 * negative sign (-) if the locale specific negative prefixes and suffixes
2199 * were present, and passing the resulting string to
2200 * {@link Long#parseLong(String, int) Long.parseLong} with the
2201 * specified radix.
2202 *
2203 * @param radix the radix used to interpret the token as an int value
2204 * @return the <tt>long</tt> scanned from the input
2205 * @throws InputMismatchException
2206 * if the next token does not match the <i>Integer</i>
2207 * regular expression, or is out of range
2208 * @throws NoSuchElementException if input is exhausted
2209 * @throws IllegalStateException if this scanner is closed
2210 */
2211 public long nextLong(int radix) {
2212 // Check cached result
2213 if ((typeCache != null) && (typeCache instanceof Long)
2214 && this.radix == radix) {
2215 long val = ((Long)typeCache).longValue();
2216 useTypeCache();
2217 return val;
2218 }
2219 setRadix(radix);
2220 clearCaches();
2221 try {
2222 String s = next(integerPattern());
2223 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2224 s = processIntegerToken(s);
2289 *
2290 * @return true if and only if this scanner's next token is a valid
2291 * float value
2292 * @throws IllegalStateException if this scanner is closed
2293 */
2294 public boolean hasNextFloat() {
2295 setRadix(10);
2296 boolean result = hasNext(floatPattern());
2297 if (result) { // Cache it
2298 try {
2299 String s = processFloatToken(hasNextResult);
2300 typeCache = Float.valueOf(Float.parseFloat(s));
2301 } catch (NumberFormatException nfe) {
2302 result = false;
2303 }
2304 }
2305 return result;
2306 }
2307
2308 /**
2309 * Scans the next token of the input as a <tt>float</tt>.
2310 * This method will throw <code>InputMismatchException</code>
2311 * if the next token cannot be translated into a valid float value as
2312 * described below. If the translation is successful, the scanner advances
2313 * past the input that matched.
2314 *
2315 * <p> If the next token matches the <a
2316 * href="#Float-regex"><i>Float</i></a> regular expression defined above
2317 * then the token is converted into a <tt>float</tt> value as if by
2318 * removing all locale specific prefixes, group separators, and locale
2319 * specific suffixes, then mapping non-ASCII digits into ASCII
2320 * digits via {@link Character#digit Character.digit}, prepending a
2321 * negative sign (-) if the locale specific negative prefixes and suffixes
2322 * were present, and passing the resulting string to
2323 * {@link Float#parseFloat Float.parseFloat}. If the token matches
2324 * the localized NaN or infinity strings, then either "Nan" or "Infinity"
2325 * is passed to {@link Float#parseFloat(String) Float.parseFloat} as
2326 * appropriate.
2327 *
2328 * @return the <tt>float</tt> scanned from the input
2329 * @throws InputMismatchException
2330 * if the next token does not match the <i>Float</i>
2331 * regular expression, or is out of range
2332 * @throws NoSuchElementException if input is exhausted
2333 * @throws IllegalStateException if this scanner is closed
2334 */
2335 public float nextFloat() {
2336 // Check cached result
2337 if ((typeCache != null) && (typeCache instanceof Float)) {
2338 float val = ((Float)typeCache).floatValue();
2339 useTypeCache();
2340 return val;
2341 }
2342 setRadix(10);
2343 clearCaches();
2344 try {
2345 return Float.parseFloat(processFloatToken(next(floatPattern())));
2346 } catch (NumberFormatException nfe) {
2347 position = matcher.start(); // don't skip bad token
2348 throw new InputMismatchException(nfe.getMessage());
2356 *
2357 * @return true if and only if this scanner's next token is a valid
2358 * double value
2359 * @throws IllegalStateException if this scanner is closed
2360 */
2361 public boolean hasNextDouble() {
2362 setRadix(10);
2363 boolean result = hasNext(floatPattern());
2364 if (result) { // Cache it
2365 try {
2366 String s = processFloatToken(hasNextResult);
2367 typeCache = Double.valueOf(Double.parseDouble(s));
2368 } catch (NumberFormatException nfe) {
2369 result = false;
2370 }
2371 }
2372 return result;
2373 }
2374
2375 /**
2376 * Scans the next token of the input as a <tt>double</tt>.
2377 * This method will throw <code>InputMismatchException</code>
2378 * if the next token cannot be translated into a valid double value.
2379 * If the translation is successful, the scanner advances past the input
2380 * that matched.
2381 *
2382 * <p> If the next token matches the <a
2383 * href="#Float-regex"><i>Float</i></a> regular expression defined above
2384 * then the token is converted into a <tt>double</tt> value as if by
2385 * removing all locale specific prefixes, group separators, and locale
2386 * specific suffixes, then mapping non-ASCII digits into ASCII
2387 * digits via {@link Character#digit Character.digit}, prepending a
2388 * negative sign (-) if the locale specific negative prefixes and suffixes
2389 * were present, and passing the resulting string to
2390 * {@link Double#parseDouble Double.parseDouble}. If the token matches
2391 * the localized NaN or infinity strings, then either "Nan" or "Infinity"
2392 * is passed to {@link Double#parseDouble(String) Double.parseDouble} as
2393 * appropriate.
2394 *
2395 * @return the <tt>double</tt> scanned from the input
2396 * @throws InputMismatchException
2397 * if the next token does not match the <i>Float</i>
2398 * regular expression, or is out of range
2399 * @throws NoSuchElementException if the input is exhausted
2400 * @throws IllegalStateException if this scanner is closed
2401 */
2402 public double nextDouble() {
2403 // Check cached result
2404 if ((typeCache != null) && (typeCache instanceof Double)) {
2405 double val = ((Double)typeCache).doubleValue();
2406 useTypeCache();
2407 return val;
2408 }
2409 setRadix(10);
2410 clearCaches();
2411 // Search for next float
2412 try {
2413 return Double.parseDouble(processFloatToken(next(floatPattern())));
2414 } catch (NumberFormatException nfe) {
2415 position = matcher.start(); // don't skip bad token
2416 throw new InputMismatchException(nfe.getMessage());
2417 }
2418 }
2419
2420 // Convenience methods for scanning multi precision numbers
2421
2422 /**
2423 * Returns true if the next token in this scanner's input can be
2424 * interpreted as a <code>BigInteger</code> in the default radix using the
2425 * {@link #nextBigInteger} method. The scanner does not advance past any
2426 * input.
2427 *
2428 * @return true if and only if this scanner's next token is a valid
2429 * <code>BigInteger</code>
2430 * @throws IllegalStateException if this scanner is closed
2431 */
2432 public boolean hasNextBigInteger() {
2433 return hasNextBigInteger(defaultRadix);
2434 }
2435
2436 /**
2437 * Returns true if the next token in this scanner's input can be
2438 * interpreted as a <code>BigInteger</code> in the specified radix using
2439 * the {@link #nextBigInteger} method. The scanner does not advance past
2440 * any input.
2441 *
2442 * @param radix the radix used to interpret the token as an integer
2443 * @return true if and only if this scanner's next token is a valid
2444 * <code>BigInteger</code>
2445 * @throws IllegalStateException if this scanner is closed
2446 */
2447 public boolean hasNextBigInteger(int radix) {
2448 setRadix(radix);
2449 boolean result = hasNext(integerPattern());
2450 if (result) { // Cache it
2451 try {
2452 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
2453 processIntegerToken(hasNextResult) :
2454 hasNextResult;
2455 typeCache = new BigInteger(s, radix);
2456 } catch (NumberFormatException nfe) {
2457 result = false;
2458 }
2459 }
2460 return result;
2461 }
2462
2463 /**
2464 * Scans the next token of the input as a {@link java.math.BigInteger
2465 * BigInteger}.
2466 *
2467 * <p> An invocation of this method of the form
2468 * <tt>nextBigInteger()</tt> behaves in exactly the same way as the
2469 * invocation <tt>nextBigInteger(radix)</tt>, where <code>radix</code>
2470 * is the default radix of this scanner.
2471 *
2472 * @return the <tt>BigInteger</tt> scanned from the input
2473 * @throws InputMismatchException
2474 * if the next token does not match the <i>Integer</i>
2475 * regular expression, or is out of range
2476 * @throws NoSuchElementException if the input is exhausted
2477 * @throws IllegalStateException if this scanner is closed
2478 */
2479 public BigInteger nextBigInteger() {
2480 return nextBigInteger(defaultRadix);
2481 }
2482
2483 /**
2484 * Scans the next token of the input as a {@link java.math.BigInteger
2485 * BigInteger}.
2486 *
2487 * <p> If the next token matches the <a
2488 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
2489 * above then the token is converted into a <tt>BigInteger</tt> value as if
2490 * by removing all group separators, mapping non-ASCII digits into ASCII
2491 * digits via the {@link Character#digit Character.digit}, and passing the
2492 * resulting string to the {@link
2493 * java.math.BigInteger#BigInteger(java.lang.String)
2494 * BigInteger(String, int)} constructor with the specified radix.
2495 *
2496 * @param radix the radix used to interpret the token
2497 * @return the <tt>BigInteger</tt> scanned from the input
2498 * @throws InputMismatchException
2499 * if the next token does not match the <i>Integer</i>
2500 * regular expression, or is out of range
2501 * @throws NoSuchElementException if the input is exhausted
2502 * @throws IllegalStateException if this scanner is closed
2503 */
2504 public BigInteger nextBigInteger(int radix) {
2505 // Check cached result
2506 if ((typeCache != null) && (typeCache instanceof BigInteger)
2507 && this.radix == radix) {
2508 BigInteger val = (BigInteger)typeCache;
2509 useTypeCache();
2510 return val;
2511 }
2512 setRadix(radix);
2513 clearCaches();
2514 // Search for next int
2515 try {
2516 String s = next(integerPattern());
2517 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2518 s = processIntegerToken(s);
2519 return new BigInteger(s, radix);
2520 } catch (NumberFormatException nfe) {
2521 position = matcher.start(); // don't skip bad token
2522 throw new InputMismatchException(nfe.getMessage());
2523 }
2524 }
2525
2526 /**
2527 * Returns true if the next token in this scanner's input can be
2528 * interpreted as a <code>BigDecimal</code> using the
2529 * {@link #nextBigDecimal} method. The scanner does not advance past any
2530 * input.
2531 *
2532 * @return true if and only if this scanner's next token is a valid
2533 * <code>BigDecimal</code>
2534 * @throws IllegalStateException if this scanner is closed
2535 */
2536 public boolean hasNextBigDecimal() {
2537 setRadix(10);
2538 boolean result = hasNext(decimalPattern());
2539 if (result) { // Cache it
2540 try {
2541 String s = processFloatToken(hasNextResult);
2542 typeCache = new BigDecimal(s);
2543 } catch (NumberFormatException nfe) {
2544 result = false;
2545 }
2546 }
2547 return result;
2548 }
2549
2550 /**
2551 * Scans the next token of the input as a {@link java.math.BigDecimal
2552 * BigDecimal}.
2553 *
2554 * <p> If the next token matches the <a
2555 * href="#Decimal-regex"><i>Decimal</i></a> regular expression defined
2556 * above then the token is converted into a <tt>BigDecimal</tt> value as if
2557 * by removing all group separators, mapping non-ASCII digits into ASCII
2558 * digits via the {@link Character#digit Character.digit}, and passing the
2559 * resulting string to the {@link
2560 * java.math.BigDecimal#BigDecimal(java.lang.String) BigDecimal(String)}
2561 * constructor.
2562 *
2563 * @return the <tt>BigDecimal</tt> scanned from the input
2564 * @throws InputMismatchException
2565 * if the next token does not match the <i>Decimal</i>
2566 * regular expression, or is out of range
2567 * @throws NoSuchElementException if the input is exhausted
2568 * @throws IllegalStateException if this scanner is closed
2569 */
2570 public BigDecimal nextBigDecimal() {
2571 // Check cached result
2572 if ((typeCache != null) && (typeCache instanceof BigDecimal)) {
2573 BigDecimal val = (BigDecimal)typeCache;
2574 useTypeCache();
2575 return val;
2576 }
2577 setRadix(10);
2578 clearCaches();
2579 // Search for next float
2580 try {
2581 String s = processFloatToken(next(decimalPattern()));
2582 return new BigDecimal(s);
2583 } catch (NumberFormatException nfe) {
2584 position = matcher.start(); // don't skip bad token
2585 throw new InputMismatchException(nfe.getMessage());
2586 }
2587 }
2588
2589 /**
2590 * Resets this scanner.
2591 *
2592 * <p> Resetting a scanner discards all of its explicit state
2593 * information which may have been changed by invocations of {@link
2594 * #useDelimiter}, {@link #useLocale}, or {@link #useRadix}.
2595 *
2596 * <p> An invocation of this method of the form
2597 * <tt>scanner.reset()</tt> behaves in exactly the same way as the
2598 * invocation
2599 *
2600 * <blockquote><pre>{@code
2601 * scanner.useDelimiter("\\p{javaWhitespace}+")
2602 * .useLocale(Locale.getDefault(Locale.Category.FORMAT))
2603 * .useRadix(10);
2604 * }</pre></blockquote>
2605 *
2606 * @return this scanner
2607 *
2608 * @since 1.6
2609 */
2610 public Scanner reset() {
2611 delimPattern = WHITESPACE_PATTERN;
2612 useLocale(Locale.getDefault(Locale.Category.FORMAT));
2613 useRadix(10);
2614 clearCaches();
2615 return this;
2616 }
2617 }
|
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} 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 {@code next} methods.
49 *
50 * <p>For example, this code allows a user to read a number from
51 * {@code System.in}:
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} types to be
58 * assigned from entries in a file {@code myNumbers}:
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:
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 {@code hasNext}
110 * and {@code next} methods may block waiting for further input. Whether a
111 * {@code hasNext} method blocks has no connection to whether or not its
112 * associated {@code next} 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 {@code "\\s+"} will return no empty
126 * tokens since it matches multiple instances of the delimiter. The delimiting
127 * pattern {@code "\\s"} 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 {@code IOException} thrown by the
135 * underlying readable can be retrieved via the {@link #ioException} method.
136 *
137 * <p>When a {@code Scanner} 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} is not safe for multithreaded use without
141 * external synchronization.
142 *
143 * <p>Unless otherwise mentioned, passing a {@code null} parameter into
144 * any method of a {@code Scanner} will cause a
145 * {@code NullPointerException} 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} regardless of whether it was previously changed.
151 *
152 * <h3> <a name="localized-numbers">Localized numbers</a> </h3>
153 *
154 * <p> An instance of this class is capable of scanning numbers in the standard
155 * formats as well as in the formats of the scanner's locale. A scanner's
156 * <a name="initial-locale">initial locale </a>is the value returned by the {@link
157 * java.util.Locale#getDefault(Locale.Category)
158 * Locale.getDefault(Locale.Category.FORMAT)} method; it may be changed via the {@link
159 * #useLocale} method. The {@link #reset} method will reset the value of the
160 * scanner's locale to the initial locale regardless of whether it was
161 * previously changed.
162 *
163 * <p>The localized formats are defined in terms of the following parameters,
164 * which for a particular locale are taken from that locale's {@link
165 * java.text.DecimalFormat DecimalFormat} object, {@code df}, and its and
166 * {@link java.text.DecimalFormatSymbols DecimalFormatSymbols} object,
167 * {@code dfs}.
168 *
169 * <blockquote><dl>
170 * <dt><i>LocalGroupSeparator </i>
171 * <dd>The character used to separate thousands groups,
172 * <i>i.e.,</i> {@code dfs.}{@link
173 * java.text.DecimalFormatSymbols#getGroupingSeparator
174 * getGroupingSeparator()}
175 * <dt><i>LocalDecimalSeparator </i>
176 * <dd>The character used for the decimal point,
177 * <i>i.e.,</i> {@code dfs.}{@link
178 * java.text.DecimalFormatSymbols#getDecimalSeparator
179 * getDecimalSeparator()}
180 * <dt><i>LocalPositivePrefix </i>
181 * <dd>The string that appears before a positive number (may
182 * be empty), <i>i.e.,</i> {@code df.}{@link
183 * java.text.DecimalFormat#getPositivePrefix
184 * getPositivePrefix()}
185 * <dt><i>LocalPositiveSuffix </i>
186 * <dd>The string that appears after a positive number (may be
187 * empty), <i>i.e.,</i> {@code df.}{@link
188 * java.text.DecimalFormat#getPositiveSuffix
189 * getPositiveSuffix()}
190 * <dt><i>LocalNegativePrefix </i>
191 * <dd>The string that appears before a negative number (may
192 * be empty), <i>i.e.,</i> {@code df.}{@link
193 * java.text.DecimalFormat#getNegativePrefix
194 * getNegativePrefix()}
195 * <dt><i>LocalNegativeSuffix </i>
196 * <dd>The string that appears after a negative number (may be
197 * empty), <i>i.e.,</i> {@code df.}{@link
198 * java.text.DecimalFormat#getNegativeSuffix
199 * getNegativeSuffix()}
200 * <dt><i>LocalNaN </i>
201 * <dd>The string that represents not-a-number for
202 * floating-point values,
203 * <i>i.e.,</i> {@code dfs.}{@link
204 * java.text.DecimalFormatSymbols#getNaN
205 * getNaN()}
206 * <dt><i>LocalInfinity </i>
207 * <dd>The string that represents infinity for floating-point
208 * values, <i>i.e.,</i> {@code dfs.}{@link
209 * java.text.DecimalFormatSymbols#getInfinity
210 * getInfinity()}
211 * </dl></blockquote>
212 *
213 * <h4> <a name="number-syntax">Number syntax</a> </h4>
214 *
215 * <p> The strings that can be parsed as numbers by an instance of this class
216 * are specified in terms of the following regular-expression grammar, where
217 * Rmax is the highest digit in the radix being used (for example, Rmax is 9 in base 10).
218 *
219 * <dl>
220 * <dt><i>NonAsciiDigit</i>:
221 * <dd>A non-ASCII character c for which
222 * {@link java.lang.Character#isDigit Character.isDigit}{@code (c)}
223 * returns true
224 *
225 * <dt><i>Non0Digit</i>:
226 * <dd>{@code [1-}<i>Rmax</i>{@code ] | }<i>NonASCIIDigit</i>
227 *
228 * <dt><i>Digit</i>:
229 * <dd>{@code [0-}<i>Rmax</i>{@code ] | }<i>NonASCIIDigit</i>
230 *
231 * <dt><i>GroupedNumeral</i>:
232 * <dd><code>( </code><i>Non0Digit</i>
233 * <i>Digit</i>{@code ?
234 * }<i>Digit</i>{@code ?}
235 * <dd> <code>( </code><i>LocalGroupSeparator</i>
236 * <i>Digit</i>
237 * <i>Digit</i>
238 * <i>Digit</i>{@code )+ )}
239 *
240 * <dt><i>Numeral</i>:
241 * <dd>{@code ( ( }<i>Digit</i>{@code + )
242 * | }<i>GroupedNumeral</i>{@code )}
243 *
244 * <dt><a name="Integer-regex"><i>Integer</i>:</a>
245 * <dd>{@code ( [-+]? ( }<i>Numeral</i>{@code
246 * ) )}
247 * <dd>{@code | }<i>LocalPositivePrefix</i> <i>Numeral</i>
248 * <i>LocalPositiveSuffix</i>
249 * <dd>{@code | }<i>LocalNegativePrefix</i> <i>Numeral</i>
250 * <i>LocalNegativeSuffix</i>
251 *
252 * <dt><i>DecimalNumeral</i>:
253 * <dd><i>Numeral</i>
254 * <dd>{@code | }<i>Numeral</i>
255 * <i>LocalDecimalSeparator</i>
256 * <i>Digit</i>{@code *}
257 * <dd>{@code | }<i>LocalDecimalSeparator</i>
258 * <i>Digit</i>{@code +}
259 *
260 * <dt><i>Exponent</i>:
261 * <dd>{@code ( [eE] [+-]? }<i>Digit</i>{@code + )}
262 *
263 * <dt><a name="Decimal-regex"><i>Decimal</i>:</a>
264 * <dd>{@code ( [-+]? }<i>DecimalNumeral</i>
265 * <i>Exponent</i>{@code ? )}
266 * <dd>{@code | }<i>LocalPositivePrefix</i>
267 * <i>DecimalNumeral</i>
268 * <i>LocalPositiveSuffix</i>
269 * <i>Exponent</i>{@code ?}
270 * <dd>{@code | }<i>LocalNegativePrefix</i>
271 * <i>DecimalNumeral</i>
272 * <i>LocalNegativeSuffix</i>
273 * <i>Exponent</i>{@code ?}
274 *
275 * <dt><i>HexFloat</i>:
276 * <dd>{@code [-+]? 0[xX][0-9a-fA-F]*\.[0-9a-fA-F]+
277 * ([pP][-+]?[0-9]+)?}
278 *
279 * <dt><i>NonNumber</i>:
280 * <dd>{@code NaN
281 * | }<i>LocalNan</i>{@code
282 * | Infinity
283 * | }<i>LocalInfinity</i>
284 *
285 * <dt><i>SignedNonNumber</i>:
286 * <dd>{@code ( [-+]? }<i>NonNumber</i>{@code )}
287 * <dd>{@code | }<i>LocalPositivePrefix</i>
288 * <i>NonNumber</i>
289 * <i>LocalPositiveSuffix</i>
290 * <dd>{@code | }<i>LocalNegativePrefix</i>
291 * <i>NonNumber</i>
292 * <i>LocalNegativeSuffix</i>
293 *
294 * <dt><a name="Float-regex"><i>Float</i></a>:
295 * <dd><i>Decimal</i>
296 * {@code | }<i>HexFloat</i>
297 * {@code | }<i>SignedNonNumber</i>
298 *
299 * </dl>
300 * <p>Whitespace is not significant in the above regular expressions.
301 *
302 * @since 1.5
303 */
304 public final class Scanner implements Iterator<String>, Closeable {
305
306 // Internal buffer used to hold input
307 private CharBuffer buf;
308
309 // Size of internal character buffer
310 private static final int BUFFER_SIZE = 1024; // change to 1024;
311
312 // The index into the buffer currently held by the Scanner
313 private int position;
314
315 // Internal matcher used for finding delimiters
316 private Matcher matcher;
317
504 floatPattern = Pattern.compile(decimal + "|" + hexFloat + "|" +
505 signedNonNumber);
506 decimalPattern = Pattern.compile(decimal);
507 }
508 private Pattern floatPattern() {
509 if (floatPattern == null) {
510 buildFloatAndDecimalPattern();
511 }
512 return floatPattern;
513 }
514 private Pattern decimalPattern() {
515 if (decimalPattern == null) {
516 buildFloatAndDecimalPattern();
517 }
518 return decimalPattern;
519 }
520
521 // Constructors
522
523 /**
524 * Constructs a {@code Scanner} that returns values scanned
525 * from the specified source delimited by the specified pattern.
526 *
527 * @param source A character source implementing the Readable interface
528 * @param pattern A delimiting pattern
529 */
530 private Scanner(Readable source, Pattern pattern) {
531 assert source != null : "source should not be null";
532 assert pattern != null : "pattern should not be null";
533 this.source = source;
534 delimPattern = pattern;
535 buf = CharBuffer.allocate(BUFFER_SIZE);
536 buf.limit(0);
537 matcher = delimPattern.matcher(buf);
538 matcher.useTransparentBounds(true);
539 matcher.useAnchoringBounds(false);
540 useLocale(Locale.getDefault(Locale.Category.FORMAT));
541 }
542
543 /**
544 * Constructs a new {@code Scanner} that produces values scanned
545 * from the specified source.
546 *
547 * @param source A character source implementing the {@link Readable}
548 * interface
549 */
550 public Scanner(Readable source) {
551 this(Objects.requireNonNull(source, "source"), WHITESPACE_PATTERN);
552 }
553
554 /**
555 * Constructs a new {@code Scanner} that produces values scanned
556 * from the specified input stream. Bytes from the stream are converted
557 * into characters using the underlying platform's
558 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
559 *
560 * @param source An input stream to be scanned
561 */
562 public Scanner(InputStream source) {
563 this(new InputStreamReader(source), WHITESPACE_PATTERN);
564 }
565
566 /**
567 * Constructs a new {@code Scanner} that produces values scanned
568 * from the specified input stream. Bytes from the stream are converted
569 * into characters using the specified charset.
570 *
571 * @param source An input stream to be scanned
572 * @param charsetName The encoding type used to convert bytes from the
573 * stream into characters to be scanned
574 * @throws IllegalArgumentException if the specified character set
575 * does not exist
576 */
577 public Scanner(InputStream source, String charsetName) {
578 this(makeReadable(Objects.requireNonNull(source, "source"), toCharset(charsetName)),
579 WHITESPACE_PATTERN);
580 }
581
582 /**
583 * Returns a charset object for the given charset name.
584 * @throws NullPointerException is csn is null
585 * @throws IllegalArgumentException if the charset is not supported
586 */
587 private static Charset toCharset(String csn) {
588 Objects.requireNonNull(csn, "charsetName");
589 try {
590 return Charset.forName(csn);
591 } catch (IllegalCharsetNameException|UnsupportedCharsetException e) {
592 // IllegalArgumentException should be thrown
593 throw new IllegalArgumentException(e);
594 }
595 }
596
597 private static Readable makeReadable(InputStream source, Charset charset) {
598 return new InputStreamReader(source, charset);
599 }
600
601 /**
602 * Constructs a new {@code Scanner} that produces values scanned
603 * from the specified file. Bytes from the file are converted into
604 * characters using the underlying platform's
605 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
606 *
607 * @param source A file to be scanned
608 * @throws FileNotFoundException if source is not found
609 */
610 public Scanner(File source) throws FileNotFoundException {
611 this((ReadableByteChannel)(new FileInputStream(source).getChannel()));
612 }
613
614 /**
615 * Constructs a new {@code Scanner} that produces values scanned
616 * from the specified file. Bytes from the file are converted into
617 * characters using the specified charset.
618 *
619 * @param source A file to be scanned
620 * @param charsetName The encoding type used to convert bytes from the file
621 * into characters to be scanned
622 * @throws FileNotFoundException if source is not found
623 * @throws IllegalArgumentException if the specified encoding is
624 * not found
625 */
626 public Scanner(File source, String charsetName)
627 throws FileNotFoundException
628 {
629 this(Objects.requireNonNull(source), toDecoder(charsetName));
630 }
631
632 private Scanner(File source, CharsetDecoder dec)
633 throws FileNotFoundException
634 {
635 this(makeReadable((ReadableByteChannel)(new FileInputStream(source).getChannel()), dec));
636 }
637
638 private static CharsetDecoder toDecoder(String charsetName) {
639 Objects.requireNonNull(charsetName, "charsetName");
640 try {
641 return Charset.forName(charsetName).newDecoder();
642 } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {
643 throw new IllegalArgumentException(charsetName);
644 }
645 }
646
647 private static Readable makeReadable(ReadableByteChannel source,
648 CharsetDecoder dec) {
649 return Channels.newReader(source, dec, -1);
650 }
651
652 /**
653 * Constructs a new {@code Scanner} that produces values scanned
654 * from the specified file. Bytes from the file are converted into
655 * characters using the underlying platform's
656 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
657 *
658 * @param source
659 * the path to the file to be scanned
660 * @throws IOException
661 * if an I/O error occurs opening source
662 *
663 * @since 1.7
664 */
665 public Scanner(Path source)
666 throws IOException
667 {
668 this(Files.newInputStream(source));
669 }
670
671 /**
672 * Constructs a new {@code Scanner} that produces values scanned
673 * from the specified file. Bytes from the file are converted into
674 * characters using the specified charset.
675 *
676 * @param source
677 * the path to the file to be scanned
678 * @param charsetName
679 * The encoding type used to convert bytes from the file
680 * into characters to be scanned
681 * @throws IOException
682 * if an I/O error occurs opening source
683 * @throws IllegalArgumentException
684 * if the specified encoding is not found
685 * @since 1.7
686 */
687 public Scanner(Path source, String charsetName) throws IOException {
688 this(Objects.requireNonNull(source), toCharset(charsetName));
689 }
690
691 private Scanner(Path source, Charset charset) throws IOException {
692 this(makeReadable(Files.newInputStream(source), charset));
693 }
694
695 /**
696 * Constructs a new {@code Scanner} that produces values scanned
697 * from the specified string.
698 *
699 * @param source A string to scan
700 */
701 public Scanner(String source) {
702 this(new StringReader(source), WHITESPACE_PATTERN);
703 }
704
705 /**
706 * Constructs a new {@code Scanner} that produces values scanned
707 * from the specified channel. Bytes from the source are converted into
708 * characters using the underlying platform's
709 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
710 *
711 * @param source A channel to scan
712 */
713 public Scanner(ReadableByteChannel source) {
714 this(makeReadable(Objects.requireNonNull(source, "source")),
715 WHITESPACE_PATTERN);
716 }
717
718 private static Readable makeReadable(ReadableByteChannel source) {
719 return makeReadable(source, Charset.defaultCharset().newDecoder());
720 }
721
722 /**
723 * Constructs a new {@code Scanner} that produces values scanned
724 * from the specified channel. Bytes from the source are converted into
725 * characters using the specified charset.
726 *
727 * @param source A channel to scan
728 * @param charsetName The encoding type used to convert bytes from the
729 * channel into characters to be scanned
730 * @throws IllegalArgumentException if the specified character set
731 * does not exist
732 */
733 public Scanner(ReadableByteChannel source, String charsetName) {
734 this(makeReadable(Objects.requireNonNull(source, "source"), toDecoder(charsetName)),
735 WHITESPACE_PATTERN);
736 }
737
738 // Private primitives used to support scanning
739
740 private void saveState() {
741 savedScannerPosition = position;
742 }
743
1060 return null;
1061
1062 // Read more to find pattern
1063 needInput = true;
1064 return null;
1065 }
1066
1067 // Throws if the scanner is closed
1068 private void ensureOpen() {
1069 if (closed)
1070 throw new IllegalStateException("Scanner closed");
1071 }
1072
1073 // Public methods
1074
1075 /**
1076 * Closes this scanner.
1077 *
1078 * <p> If this scanner has not yet been closed then if its underlying
1079 * {@linkplain java.lang.Readable readable} also implements the {@link
1080 * java.io.Closeable} interface then the readable's {@code close} method
1081 * will be invoked. If this scanner is already closed then invoking this
1082 * method will have no effect.
1083 *
1084 * <p>Attempting to perform search operations after a scanner has
1085 * been closed will result in an {@link IllegalStateException}.
1086 *
1087 */
1088 public void close() {
1089 if (closed)
1090 return;
1091 if (source instanceof Closeable) {
1092 try {
1093 ((Closeable)source).close();
1094 } catch (IOException ioe) {
1095 lastException = ioe;
1096 }
1097 }
1098 sourceClosed = true;
1099 source = null;
1100 closed = true;
1101 }
1102
1103 /**
1104 * Returns the {@code IOException} last thrown by this
1105 * {@code Scanner}'s underlying {@code Readable}. This method
1106 * returns {@code null} if no such exception exists.
1107 *
1108 * @return the last exception thrown by this scanner's readable
1109 */
1110 public IOException ioException() {
1111 return lastException;
1112 }
1113
1114 /**
1115 * Returns the {@code Pattern} this {@code Scanner} is currently
1116 * using to match delimiters.
1117 *
1118 * @return this scanner's delimiting pattern.
1119 */
1120 public Pattern delimiter() {
1121 return delimPattern;
1122 }
1123
1124 /**
1125 * Sets this scanner's delimiting pattern to the specified pattern.
1126 *
1127 * @param pattern A delimiting pattern
1128 * @return this scanner
1129 */
1130 public Scanner useDelimiter(Pattern pattern) {
1131 delimPattern = pattern;
1132 return this;
1133 }
1134
1135 /**
1136 * Sets this scanner's delimiting pattern to a pattern constructed from
1137 * the specified {@code String}.
1138 *
1139 * <p> An invocation of this method of the form
1140 * {@code useDelimiter(pattern)} behaves in exactly the same way as the
1141 * invocation {@code useDelimiter(Pattern.compile(pattern))}.
1142 *
1143 * <p> Invoking the {@link #reset} method will set the scanner's delimiter
1144 * to the <a href= "#default-delimiter">default</a>.
1145 *
1146 * @param pattern A string specifying a delimiting pattern
1147 * @return this scanner
1148 */
1149 public Scanner useDelimiter(String pattern) {
1150 delimPattern = patternCache.forName(pattern);
1151 return this;
1152 }
1153
1154 /**
1155 * Returns this scanner's locale.
1156 *
1157 * <p>A scanner's locale affects many elements of its default
1158 * primitive matching regular expressions; see
1159 * <a href= "#localized-numbers">localized numbers</a> above.
1160 *
1161 * @return this scanner's locale
1219 /**
1220 * Returns this scanner's default radix.
1221 *
1222 * <p>A scanner's radix affects elements of its default
1223 * number matching regular expressions; see
1224 * <a href= "#localized-numbers">localized numbers</a> above.
1225 *
1226 * @return the default radix of this scanner
1227 */
1228 public int radix() {
1229 return this.defaultRadix;
1230 }
1231
1232 /**
1233 * Sets this scanner's default radix to the specified radix.
1234 *
1235 * <p>A scanner's radix affects elements of its default
1236 * number matching regular expressions; see
1237 * <a href= "#localized-numbers">localized numbers</a> above.
1238 *
1239 * <p>If the radix is less than {@code Character.MIN_RADIX}
1240 * or greater than {@code Character.MAX_RADIX}, then an
1241 * {@code IllegalArgumentException} is thrown.
1242 *
1243 * <p>Invoking the {@link #reset} method will set the scanner's radix to
1244 * {@code 10}.
1245 *
1246 * @param radix The radix to use when scanning numbers
1247 * @return this scanner
1248 * @throws IllegalArgumentException if radix is out of range
1249 */
1250 public Scanner useRadix(int radix) {
1251 if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX))
1252 throw new IllegalArgumentException("radix:"+radix);
1253
1254 if (this.defaultRadix == radix)
1255 return this;
1256 this.defaultRadix = radix;
1257 // Force rebuilding and recompilation of radix dependent patterns
1258 integerPattern = null;
1259 return this;
1260 }
1261
1262 // The next operation should occur in the specified radix but
1263 // the default is left untouched.
1264 private void setRadix(int radix) {
1265 if (this.radix != radix) {
1266 // Force rebuilding and recompilation of radix dependent patterns
1267 integerPattern = null;
1268 this.radix = radix;
1269 }
1270 }
1271
1272 /**
1273 * Returns the match result of the last scanning operation performed
1274 * by this scanner. This method throws {@code IllegalStateException}
1275 * if no match has been performed, or if the last match was
1276 * not successful.
1277 *
1278 * <p>The various {@code next}methods of {@code Scanner}
1279 * make a match result available if they complete without throwing an
1280 * exception. For instance, after an invocation of the {@link #nextInt}
1281 * method that returned an int, this method returns a
1282 * {@code MatchResult} for the search of the
1283 * <a href="#Integer-regex"><i>Integer</i></a> regular expression
1284 * defined above. Similarly the {@link #findInLine},
1285 * {@link #findWithinHorizon}, and {@link #skip} methods will make a
1286 * match available if they succeed.
1287 *
1288 * @return a match result for the last match operation
1289 * @throws IllegalStateException If no match result is available
1290 */
1291 public MatchResult match() {
1292 if (!matchValid)
1293 throw new IllegalStateException("No match result available");
1294 return matcher.toMatchResult();
1295 }
1296
1297 /**
1298 * <p>Returns the string representation of this {@code Scanner}. The
1299 * string representation of a {@code Scanner} contains information
1300 * that may be useful for debugging. The exact format is unspecified.
1301 *
1302 * @return The string representation of this scanner
1303 */
1304 public String toString() {
1305 StringBuilder sb = new StringBuilder();
1306 sb.append("java.util.Scanner");
1307 sb.append("[delimiters=" + delimPattern + "]");
1308 sb.append("[position=" + position + "]");
1309 sb.append("[match valid=" + matchValid + "]");
1310 sb.append("[need input=" + needInput + "]");
1311 sb.append("[source closed=" + sourceClosed + "]");
1312 sb.append("[skipped=" + skipped + "]");
1313 sb.append("[group separator=" + groupSeparator + "]");
1314 sb.append("[decimal separator=" + decimalSeparator + "]");
1315 sb.append("[positive prefix=" + positivePrefix + "]");
1316 sb.append("[negative prefix=" + negativePrefix + "]");
1317 sb.append("[positive suffix=" + positiveSuffix + "]");
1318 sb.append("[negative suffix=" + negativeSuffix + "]");
1319 sb.append("[NaN string=" + nanString + "]");
1330 * @throws IllegalStateException if this scanner is closed
1331 * @see java.util.Iterator
1332 */
1333 public boolean hasNext() {
1334 ensureOpen();
1335 saveState();
1336 while (!sourceClosed) {
1337 if (hasTokenInBuffer())
1338 return revertState(true);
1339 readInput();
1340 }
1341 boolean result = hasTokenInBuffer();
1342 return revertState(result);
1343 }
1344
1345 /**
1346 * Finds and returns the next complete token from this scanner.
1347 * A complete token is preceded and followed by input that matches
1348 * the delimiter pattern. This method may block while waiting for input
1349 * to scan, even if a previous invocation of {@link #hasNext} returned
1350 * {@code true}.
1351 *
1352 * @return the next token
1353 * @throws NoSuchElementException if no more tokens are available
1354 * @throws IllegalStateException if this scanner is closed
1355 * @see java.util.Iterator
1356 */
1357 public String next() {
1358 ensureOpen();
1359 clearCaches();
1360
1361 while (true) {
1362 String token = getCompleteTokenInBuffer(null);
1363 if (token != null) {
1364 matchValid = true;
1365 skipped = false;
1366 return token;
1367 }
1368 if (needInput)
1369 readInput();
1370 else
1371 throwFor();
1372 }
1373 }
1374
1375 /**
1376 * The remove operation is not supported by this implementation of
1377 * {@code Iterator}.
1378 *
1379 * @throws UnsupportedOperationException if this method is invoked.
1380 * @see java.util.Iterator
1381 */
1382 public void remove() {
1383 throw new UnsupportedOperationException();
1384 }
1385
1386 /**
1387 * Returns true if the next token matches the pattern constructed from the
1388 * specified string. The scanner does not advance past any input.
1389 *
1390 * <p> An invocation of this method of the form {@code hasNext(pattern)}
1391 * behaves in exactly the same way as the invocation
1392 * {@code hasNext(Pattern.compile(pattern))}.
1393 *
1394 * @param pattern a string specifying the pattern to scan
1395 * @return true if and only if this scanner has another token matching
1396 * the specified pattern
1397 * @throws IllegalStateException if this scanner is closed
1398 */
1399 public boolean hasNext(String pattern) {
1400 return hasNext(patternCache.forName(pattern));
1401 }
1402
1403 /**
1404 * Returns the next token if it matches the pattern constructed from the
1405 * specified string. If the match is successful, the scanner advances
1406 * past the input that matched the pattern.
1407 *
1408 * <p> An invocation of this method of the form {@code next(pattern)}
1409 * behaves in exactly the same way as the invocation
1410 * {@code next(Pattern.compile(pattern))}.
1411 *
1412 * @param pattern a string specifying the pattern to scan
1413 * @return the next token
1414 * @throws NoSuchElementException if no such tokens are available
1415 * @throws IllegalStateException if this scanner is closed
1416 */
1417 public String next(String pattern) {
1418 return next(patternCache.forName(pattern));
1419 }
1420
1421 /**
1422 * Returns true if the next complete token matches the specified pattern.
1423 * A complete token is prefixed and postfixed by input that matches
1424 * the delimiter pattern. This method may block while waiting for input.
1425 * The scanner does not advance past any input.
1426 *
1427 * @param pattern the pattern to scan for
1428 * @return true if and only if this scanner has another token matching
1429 * the specified pattern
1430 * @throws IllegalStateException if this scanner is closed
1435 throw new NullPointerException();
1436 hasNextPattern = null;
1437 saveState();
1438
1439 while (true) {
1440 if (getCompleteTokenInBuffer(pattern) != null) {
1441 matchValid = true;
1442 cacheResult();
1443 return revertState(true);
1444 }
1445 if (needInput)
1446 readInput();
1447 else
1448 return revertState(false);
1449 }
1450 }
1451
1452 /**
1453 * Returns the next token if it matches the specified pattern. This
1454 * method may block while waiting for input to scan, even if a previous
1455 * invocation of {@link #hasNext(Pattern)} returned {@code true}.
1456 * If the match is successful, the scanner advances past the input that
1457 * matched the pattern.
1458 *
1459 * @param pattern the pattern to scan for
1460 * @return the next token
1461 * @throws NoSuchElementException if no more tokens are available
1462 * @throws IllegalStateException if this scanner is closed
1463 */
1464 public String next(Pattern pattern) {
1465 ensureOpen();
1466 if (pattern == null)
1467 throw new NullPointerException();
1468
1469 // Did we already find this pattern?
1470 if (hasNextPattern == pattern)
1471 return getCachedResult();
1472 clearCaches();
1473
1474 // Search for the pattern
1475 while (true) {
1537
1538 String result = findWithinHorizon(linePattern, 0);
1539 if (result == null)
1540 throw new NoSuchElementException("No line found");
1541 MatchResult mr = this.match();
1542 String lineSep = mr.group(1);
1543 if (lineSep != null)
1544 result = result.substring(0, result.length() - lineSep.length());
1545 if (result == null)
1546 throw new NoSuchElementException();
1547 else
1548 return result;
1549 }
1550
1551 // Public methods that ignore delimiters
1552
1553 /**
1554 * Attempts to find the next occurrence of a pattern constructed from the
1555 * specified string, ignoring delimiters.
1556 *
1557 * <p>An invocation of this method of the form {@code findInLine(pattern)}
1558 * behaves in exactly the same way as the invocation
1559 * {@code findInLine(Pattern.compile(pattern))}.
1560 *
1561 * @param pattern a string specifying the pattern to search for
1562 * @return the text that matched the specified pattern
1563 * @throws IllegalStateException if this scanner is closed
1564 */
1565 public String findInLine(String pattern) {
1566 return findInLine(patternCache.forName(pattern));
1567 }
1568
1569 /**
1570 * Attempts to find the next occurrence of the specified pattern ignoring
1571 * delimiters. If the pattern is found before the next line separator, the
1572 * scanner advances past the input that matched and returns the string that
1573 * matched the pattern.
1574 * If no such pattern is detected in the input up to the next line
1575 * separator, then {@code null} is returned and the scanner's
1576 * position is unchanged. This method may block waiting for input that
1577 * matches the pattern.
1578 *
1579 * <p>Since this method continues to search through the input looking
1580 * for the specified pattern, it may buffer all of the input searching for
1581 * the desired token if no line separators are present.
1582 *
1583 * @param pattern the pattern to scan for
1584 * @return the text that matched the specified pattern
1585 * @throws IllegalStateException if this scanner is closed
1586 */
1587 public String findInLine(Pattern pattern) {
1588 ensureOpen();
1589 if (pattern == null)
1590 throw new NullPointerException();
1591 clearCaches();
1592 // Expand buffer to include the next newline or end of input
1593 int endPosition = 0;
1594 saveState();
1595 while (true) {
1604 endPosition = buf.limit();
1605 break; // up to end of input
1606 }
1607 }
1608 revertState();
1609 int horizonForLine = endPosition - position;
1610 // If there is nothing between the current pos and the next
1611 // newline simply return null, invoking findWithinHorizon
1612 // with "horizon=0" will scan beyond the line bound.
1613 if (horizonForLine == 0)
1614 return null;
1615 // Search for the pattern
1616 return findWithinHorizon(pattern, horizonForLine);
1617 }
1618
1619 /**
1620 * Attempts to find the next occurrence of a pattern constructed from the
1621 * specified string, ignoring delimiters.
1622 *
1623 * <p>An invocation of this method of the form
1624 * {@code findWithinHorizon(pattern)} behaves in exactly the same way as
1625 * the invocation
1626 * {@code findWithinHorizon(Pattern.compile(pattern, horizon))}.
1627 *
1628 * @param pattern a string specifying the pattern to search for
1629 * @param horizon the search horizon
1630 * @return the text that matched the specified pattern
1631 * @throws IllegalStateException if this scanner is closed
1632 * @throws IllegalArgumentException if horizon is negative
1633 */
1634 public String findWithinHorizon(String pattern, int horizon) {
1635 return findWithinHorizon(patternCache.forName(pattern), horizon);
1636 }
1637
1638 /**
1639 * Attempts to find the next occurrence of the specified pattern.
1640 *
1641 * <p>This method searches through the input up to the specified
1642 * search horizon, ignoring delimiters. If the pattern is found the
1643 * scanner advances past the input that matched and returns the string
1644 * that matched the pattern. If no such pattern is detected then the
1645 * null is returned and the scanner's position remains unchanged. This
1646 * method may block waiting for input that matches the pattern.
1647 *
1648 * <p>A scanner will never search more than {@code horizon} code
1649 * points beyond its current position. Note that a match may be clipped
1650 * by the horizon; that is, an arbitrary match result may have been
1651 * different if the horizon had been larger. The scanner treats the
1652 * horizon as a transparent, non-anchoring bound (see {@link
1653 * Matcher#useTransparentBounds} and {@link Matcher#useAnchoringBounds}).
1654 *
1655 * <p>If horizon is {@code 0}, then the horizon is ignored and
1656 * this method continues to search through the input looking for the
1657 * specified pattern without bound. In this case it may buffer all of
1658 * the input searching for the pattern.
1659 *
1660 * <p>If horizon is negative, then an IllegalArgumentException is
1661 * thrown.
1662 *
1663 * @param pattern the pattern to scan for
1664 * @param horizon the search horizon
1665 * @return the text that matched the specified pattern
1666 * @throws IllegalStateException if this scanner is closed
1667 * @throws IllegalArgumentException if horizon is negative
1668 */
1669 public String findWithinHorizon(Pattern pattern, int horizon) {
1670 ensureOpen();
1671 if (pattern == null)
1672 throw new NullPointerException();
1673 if (horizon < 0)
1674 throw new IllegalArgumentException("horizon < 0");
1675 clearCaches();
1679 String token = findPatternInBuffer(pattern, horizon);
1680 if (token != null) {
1681 matchValid = true;
1682 return token;
1683 }
1684 if (needInput)
1685 readInput();
1686 else
1687 break; // up to end of input
1688 }
1689 return null;
1690 }
1691
1692 /**
1693 * Skips input that matches the specified pattern, ignoring delimiters.
1694 * This method will skip input if an anchored match of the specified
1695 * pattern succeeds.
1696 *
1697 * <p>If a match to the specified pattern is not found at the
1698 * current position, then no input is skipped and a
1699 * {@code NoSuchElementException} is thrown.
1700 *
1701 * <p>Since this method seeks to match the specified pattern starting at
1702 * the scanner's current position, patterns that can match a lot of
1703 * input (".*", for example) may cause the scanner to buffer a large
1704 * amount of input.
1705 *
1706 * <p>Note that it is possible to skip something without risking a
1707 * {@code NoSuchElementException} by using a pattern that can
1708 * match nothing, e.g., {@code sc.skip("[ \t]*")}.
1709 *
1710 * @param pattern a string specifying the pattern to skip over
1711 * @return this scanner
1712 * @throws NoSuchElementException if the specified pattern is not found
1713 * @throws IllegalStateException if this scanner is closed
1714 */
1715 public Scanner skip(Pattern pattern) {
1716 ensureOpen();
1717 if (pattern == null)
1718 throw new NullPointerException();
1719 clearCaches();
1720
1721 // Search for the pattern
1722 while (true) {
1723 String token = matchPatternInBuffer(pattern);
1724 if (token != null) {
1725 matchValid = true;
1726 position = matcher.end();
1727 return this;
1728 }
1729 if (needInput)
1730 readInput();
1731 else
1732 throw new NoSuchElementException();
1733 }
1734 }
1735
1736 /**
1737 * Skips input that matches a pattern constructed from the specified
1738 * string.
1739 *
1740 * <p> An invocation of this method of the form {@code skip(pattern)}
1741 * behaves in exactly the same way as the invocation
1742 * {@code skip(Pattern.compile(pattern))}.
1743 *
1744 * @param pattern a string specifying the pattern to skip over
1745 * @return this scanner
1746 * @throws IllegalStateException if this scanner is closed
1747 */
1748 public Scanner skip(String pattern) {
1749 return skip(patternCache.forName(pattern));
1750 }
1751
1752 // Convenience methods for scanning primitives
1753
1754 /**
1755 * Returns true if the next token in this scanner's input can be
1756 * interpreted as a boolean value using a case insensitive pattern
1757 * created from the string "true|false". The scanner does not
1758 * advance past the input that matched.
1759 *
1760 * @return true if and only if this scanner's next token is a valid
1761 * boolean value
1762 * @throws IllegalStateException if this scanner is closed
1763 */
1764 public boolean hasNextBoolean() {
1765 return hasNext(boolPattern());
1766 }
1767
1768 /**
1769 * Scans the next token of the input into a boolean value and returns
1770 * that value. This method will throw {@code InputMismatchException}
1771 * if the next token cannot be translated into a valid boolean value.
1772 * If the match is successful, the scanner advances past the input that
1773 * matched.
1774 *
1775 * @return the boolean scanned from the input
1776 * @throws InputMismatchException if the next token is not a valid boolean
1777 * @throws NoSuchElementException if input is exhausted
1778 * @throws IllegalStateException if this scanner is closed
1779 */
1780 public boolean nextBoolean() {
1781 clearCaches();
1782 return Boolean.parseBoolean(next(boolPattern()));
1783 }
1784
1785 /**
1786 * Returns true if the next token in this scanner's input can be
1787 * interpreted as a byte value in the default radix using the
1788 * {@link #nextByte} method. The scanner does not advance past any input.
1789 *
1790 * @return true if and only if this scanner's next token is a valid
1805 * byte value
1806 * @throws IllegalStateException if this scanner is closed
1807 */
1808 public boolean hasNextByte(int radix) {
1809 setRadix(radix);
1810 boolean result = hasNext(integerPattern());
1811 if (result) { // Cache it
1812 try {
1813 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
1814 processIntegerToken(hasNextResult) :
1815 hasNextResult;
1816 typeCache = Byte.parseByte(s, radix);
1817 } catch (NumberFormatException nfe) {
1818 result = false;
1819 }
1820 }
1821 return result;
1822 }
1823
1824 /**
1825 * Scans the next token of the input as a {@code byte}.
1826 *
1827 * <p> An invocation of this method of the form
1828 * {@code nextByte()} behaves in exactly the same way as the
1829 * invocation {@code nextByte(radix)}, where {@code radix}
1830 * is the default radix of this scanner.
1831 *
1832 * @return the {@code byte} scanned from the input
1833 * @throws InputMismatchException
1834 * if the next token does not match the <i>Integer</i>
1835 * regular expression, or is out of range
1836 * @throws NoSuchElementException if input is exhausted
1837 * @throws IllegalStateException if this scanner is closed
1838 */
1839 public byte nextByte() {
1840 return nextByte(defaultRadix);
1841 }
1842
1843 /**
1844 * Scans the next token of the input as a {@code byte}.
1845 * This method will throw {@code InputMismatchException}
1846 * if the next token cannot be translated into a valid byte value as
1847 * described below. If the translation is successful, the scanner advances
1848 * past the input that matched.
1849 *
1850 * <p> If the next token matches the <a
1851 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
1852 * above then the token is converted into a {@code byte} value as if by
1853 * removing all locale specific prefixes, group separators, and locale
1854 * specific suffixes, then mapping non-ASCII digits into ASCII
1855 * digits via {@link Character#digit Character.digit}, prepending a
1856 * negative sign (-) if the locale specific negative prefixes and suffixes
1857 * were present, and passing the resulting string to
1858 * {@link Byte#parseByte(String, int) Byte.parseByte} with the
1859 * specified radix.
1860 *
1861 * @param radix the radix used to interpret the token as a byte value
1862 * @return the {@code byte} scanned from the input
1863 * @throws InputMismatchException
1864 * if the next token does not match the <i>Integer</i>
1865 * regular expression, or is out of range
1866 * @throws NoSuchElementException if input is exhausted
1867 * @throws IllegalStateException if this scanner is closed
1868 */
1869 public byte nextByte(int radix) {
1870 // Check cached result
1871 if ((typeCache != null) && (typeCache instanceof Byte)
1872 && this.radix == radix) {
1873 byte val = ((Byte)typeCache).byteValue();
1874 useTypeCache();
1875 return val;
1876 }
1877 setRadix(radix);
1878 clearCaches();
1879 // Search for next byte
1880 try {
1881 String s = next(integerPattern());
1882 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
1911 * short value in the specified radix
1912 * @throws IllegalStateException if this scanner is closed
1913 */
1914 public boolean hasNextShort(int radix) {
1915 setRadix(radix);
1916 boolean result = hasNext(integerPattern());
1917 if (result) { // Cache it
1918 try {
1919 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
1920 processIntegerToken(hasNextResult) :
1921 hasNextResult;
1922 typeCache = Short.parseShort(s, radix);
1923 } catch (NumberFormatException nfe) {
1924 result = false;
1925 }
1926 }
1927 return result;
1928 }
1929
1930 /**
1931 * Scans the next token of the input as a {@code short}.
1932 *
1933 * <p> An invocation of this method of the form
1934 * {@code nextShort()} behaves in exactly the same way as the
1935 * invocation {@code nextShort(radix)}, where {@code radix}
1936 * is the default radix of this scanner.
1937 *
1938 * @return the {@code short} scanned from the input
1939 * @throws InputMismatchException
1940 * if the next token does not match the <i>Integer</i>
1941 * regular expression, or is out of range
1942 * @throws NoSuchElementException if input is exhausted
1943 * @throws IllegalStateException if this scanner is closed
1944 */
1945 public short nextShort() {
1946 return nextShort(defaultRadix);
1947 }
1948
1949 /**
1950 * Scans the next token of the input as a {@code short}.
1951 * This method will throw {@code InputMismatchException}
1952 * if the next token cannot be translated into a valid short value as
1953 * described below. If the translation is successful, the scanner advances
1954 * past the input that matched.
1955 *
1956 * <p> If the next token matches the <a
1957 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
1958 * above then the token is converted into a {@code short} value as if by
1959 * removing all locale specific prefixes, group separators, and locale
1960 * specific suffixes, then mapping non-ASCII digits into ASCII
1961 * digits via {@link Character#digit Character.digit}, prepending a
1962 * negative sign (-) if the locale specific negative prefixes and suffixes
1963 * were present, and passing the resulting string to
1964 * {@link Short#parseShort(String, int) Short.parseShort} with the
1965 * specified radix.
1966 *
1967 * @param radix the radix used to interpret the token as a short value
1968 * @return the {@code short} scanned from the input
1969 * @throws InputMismatchException
1970 * if the next token does not match the <i>Integer</i>
1971 * regular expression, or is out of range
1972 * @throws NoSuchElementException if input is exhausted
1973 * @throws IllegalStateException if this scanner is closed
1974 */
1975 public short nextShort(int radix) {
1976 // Check cached result
1977 if ((typeCache != null) && (typeCache instanceof Short)
1978 && this.radix == radix) {
1979 short val = ((Short)typeCache).shortValue();
1980 useTypeCache();
1981 return val;
1982 }
1983 setRadix(radix);
1984 clearCaches();
1985 // Search for next short
1986 try {
1987 String s = next(integerPattern());
1988 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2041 private String processIntegerToken(String token) {
2042 String result = token.replaceAll(""+groupSeparator, "");
2043 boolean isNegative = false;
2044 int preLen = negativePrefix.length();
2045 if ((preLen > 0) && result.startsWith(negativePrefix)) {
2046 isNegative = true;
2047 result = result.substring(preLen);
2048 }
2049 int sufLen = negativeSuffix.length();
2050 if ((sufLen > 0) && result.endsWith(negativeSuffix)) {
2051 isNegative = true;
2052 result = result.substring(result.length() - sufLen,
2053 result.length());
2054 }
2055 if (isNegative)
2056 result = "-" + result;
2057 return result;
2058 }
2059
2060 /**
2061 * Scans the next token of the input as an {@code int}.
2062 *
2063 * <p> An invocation of this method of the form
2064 * {@code nextInt()} behaves in exactly the same way as the
2065 * invocation {@code nextInt(radix)}, where {@code radix}
2066 * is the default radix of this scanner.
2067 *
2068 * @return the {@code int} scanned from the input
2069 * @throws InputMismatchException
2070 * if the next token does not match the <i>Integer</i>
2071 * regular expression, or is out of range
2072 * @throws NoSuchElementException if input is exhausted
2073 * @throws IllegalStateException if this scanner is closed
2074 */
2075 public int nextInt() {
2076 return nextInt(defaultRadix);
2077 }
2078
2079 /**
2080 * Scans the next token of the input as an {@code int}.
2081 * This method will throw {@code InputMismatchException}
2082 * if the next token cannot be translated into a valid int value as
2083 * described below. If the translation is successful, the scanner advances
2084 * past the input that matched.
2085 *
2086 * <p> If the next token matches the <a
2087 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
2088 * above then the token is converted into an {@code int} value as if by
2089 * removing all locale specific prefixes, group separators, and locale
2090 * specific suffixes, then mapping non-ASCII digits into ASCII
2091 * digits via {@link Character#digit Character.digit}, prepending a
2092 * negative sign (-) if the locale specific negative prefixes and suffixes
2093 * were present, and passing the resulting string to
2094 * {@link Integer#parseInt(String, int) Integer.parseInt} with the
2095 * specified radix.
2096 *
2097 * @param radix the radix used to interpret the token as an int value
2098 * @return the {@code int} scanned from the input
2099 * @throws InputMismatchException
2100 * if the next token does not match the <i>Integer</i>
2101 * regular expression, or is out of range
2102 * @throws NoSuchElementException if input is exhausted
2103 * @throws IllegalStateException if this scanner is closed
2104 */
2105 public int nextInt(int radix) {
2106 // Check cached result
2107 if ((typeCache != null) && (typeCache instanceof Integer)
2108 && this.radix == radix) {
2109 int val = ((Integer)typeCache).intValue();
2110 useTypeCache();
2111 return val;
2112 }
2113 setRadix(radix);
2114 clearCaches();
2115 // Search for next int
2116 try {
2117 String s = next(integerPattern());
2118 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2147 * long value
2148 * @throws IllegalStateException if this scanner is closed
2149 */
2150 public boolean hasNextLong(int radix) {
2151 setRadix(radix);
2152 boolean result = hasNext(integerPattern());
2153 if (result) { // Cache it
2154 try {
2155 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
2156 processIntegerToken(hasNextResult) :
2157 hasNextResult;
2158 typeCache = Long.parseLong(s, radix);
2159 } catch (NumberFormatException nfe) {
2160 result = false;
2161 }
2162 }
2163 return result;
2164 }
2165
2166 /**
2167 * Scans the next token of the input as a {@code long}.
2168 *
2169 * <p> An invocation of this method of the form
2170 * {@code nextLong()} behaves in exactly the same way as the
2171 * invocation {@code nextLong(radix)}, where {@code radix}
2172 * is the default radix of this scanner.
2173 *
2174 * @return the {@code long} scanned from the input
2175 * @throws InputMismatchException
2176 * if the next token does not match the <i>Integer</i>
2177 * regular expression, or is out of range
2178 * @throws NoSuchElementException if input is exhausted
2179 * @throws IllegalStateException if this scanner is closed
2180 */
2181 public long nextLong() {
2182 return nextLong(defaultRadix);
2183 }
2184
2185 /**
2186 * Scans the next token of the input as a {@code long}.
2187 * This method will throw {@code InputMismatchException}
2188 * if the next token cannot be translated into a valid long value as
2189 * described below. If the translation is successful, the scanner advances
2190 * past the input that matched.
2191 *
2192 * <p> If the next token matches the <a
2193 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
2194 * above then the token is converted into a {@code long} value as if by
2195 * removing all locale specific prefixes, group separators, and locale
2196 * specific suffixes, then mapping non-ASCII digits into ASCII
2197 * digits via {@link Character#digit Character.digit}, prepending a
2198 * negative sign (-) if the locale specific negative prefixes and suffixes
2199 * were present, and passing the resulting string to
2200 * {@link Long#parseLong(String, int) Long.parseLong} with the
2201 * specified radix.
2202 *
2203 * @param radix the radix used to interpret the token as an int value
2204 * @return the {@code long} scanned from the input
2205 * @throws InputMismatchException
2206 * if the next token does not match the <i>Integer</i>
2207 * regular expression, or is out of range
2208 * @throws NoSuchElementException if input is exhausted
2209 * @throws IllegalStateException if this scanner is closed
2210 */
2211 public long nextLong(int radix) {
2212 // Check cached result
2213 if ((typeCache != null) && (typeCache instanceof Long)
2214 && this.radix == radix) {
2215 long val = ((Long)typeCache).longValue();
2216 useTypeCache();
2217 return val;
2218 }
2219 setRadix(radix);
2220 clearCaches();
2221 try {
2222 String s = next(integerPattern());
2223 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2224 s = processIntegerToken(s);
2289 *
2290 * @return true if and only if this scanner's next token is a valid
2291 * float value
2292 * @throws IllegalStateException if this scanner is closed
2293 */
2294 public boolean hasNextFloat() {
2295 setRadix(10);
2296 boolean result = hasNext(floatPattern());
2297 if (result) { // Cache it
2298 try {
2299 String s = processFloatToken(hasNextResult);
2300 typeCache = Float.valueOf(Float.parseFloat(s));
2301 } catch (NumberFormatException nfe) {
2302 result = false;
2303 }
2304 }
2305 return result;
2306 }
2307
2308 /**
2309 * Scans the next token of the input as a {@code float}.
2310 * This method will throw {@code InputMismatchException}
2311 * if the next token cannot be translated into a valid float value as
2312 * described below. If the translation is successful, the scanner advances
2313 * past the input that matched.
2314 *
2315 * <p> If the next token matches the <a
2316 * href="#Float-regex"><i>Float</i></a> regular expression defined above
2317 * then the token is converted into a {@code float} value as if by
2318 * removing all locale specific prefixes, group separators, and locale
2319 * specific suffixes, then mapping non-ASCII digits into ASCII
2320 * digits via {@link Character#digit Character.digit}, prepending a
2321 * negative sign (-) if the locale specific negative prefixes and suffixes
2322 * were present, and passing the resulting string to
2323 * {@link Float#parseFloat Float.parseFloat}. If the token matches
2324 * the localized NaN or infinity strings, then either "Nan" or "Infinity"
2325 * is passed to {@link Float#parseFloat(String) Float.parseFloat} as
2326 * appropriate.
2327 *
2328 * @return the {@code float} scanned from the input
2329 * @throws InputMismatchException
2330 * if the next token does not match the <i>Float</i>
2331 * regular expression, or is out of range
2332 * @throws NoSuchElementException if input is exhausted
2333 * @throws IllegalStateException if this scanner is closed
2334 */
2335 public float nextFloat() {
2336 // Check cached result
2337 if ((typeCache != null) && (typeCache instanceof Float)) {
2338 float val = ((Float)typeCache).floatValue();
2339 useTypeCache();
2340 return val;
2341 }
2342 setRadix(10);
2343 clearCaches();
2344 try {
2345 return Float.parseFloat(processFloatToken(next(floatPattern())));
2346 } catch (NumberFormatException nfe) {
2347 position = matcher.start(); // don't skip bad token
2348 throw new InputMismatchException(nfe.getMessage());
2356 *
2357 * @return true if and only if this scanner's next token is a valid
2358 * double value
2359 * @throws IllegalStateException if this scanner is closed
2360 */
2361 public boolean hasNextDouble() {
2362 setRadix(10);
2363 boolean result = hasNext(floatPattern());
2364 if (result) { // Cache it
2365 try {
2366 String s = processFloatToken(hasNextResult);
2367 typeCache = Double.valueOf(Double.parseDouble(s));
2368 } catch (NumberFormatException nfe) {
2369 result = false;
2370 }
2371 }
2372 return result;
2373 }
2374
2375 /**
2376 * Scans the next token of the input as a {@code double}.
2377 * This method will throw {@code InputMismatchException}
2378 * if the next token cannot be translated into a valid double value.
2379 * If the translation is successful, the scanner advances past the input
2380 * that matched.
2381 *
2382 * <p> If the next token matches the <a
2383 * href="#Float-regex"><i>Float</i></a> regular expression defined above
2384 * then the token is converted into a {@code double} value as if by
2385 * removing all locale specific prefixes, group separators, and locale
2386 * specific suffixes, then mapping non-ASCII digits into ASCII
2387 * digits via {@link Character#digit Character.digit}, prepending a
2388 * negative sign (-) if the locale specific negative prefixes and suffixes
2389 * were present, and passing the resulting string to
2390 * {@link Double#parseDouble Double.parseDouble}. If the token matches
2391 * the localized NaN or infinity strings, then either "Nan" or "Infinity"
2392 * is passed to {@link Double#parseDouble(String) Double.parseDouble} as
2393 * appropriate.
2394 *
2395 * @return the {@code double} scanned from the input
2396 * @throws InputMismatchException
2397 * if the next token does not match the <i>Float</i>
2398 * regular expression, or is out of range
2399 * @throws NoSuchElementException if the input is exhausted
2400 * @throws IllegalStateException if this scanner is closed
2401 */
2402 public double nextDouble() {
2403 // Check cached result
2404 if ((typeCache != null) && (typeCache instanceof Double)) {
2405 double val = ((Double)typeCache).doubleValue();
2406 useTypeCache();
2407 return val;
2408 }
2409 setRadix(10);
2410 clearCaches();
2411 // Search for next float
2412 try {
2413 return Double.parseDouble(processFloatToken(next(floatPattern())));
2414 } catch (NumberFormatException nfe) {
2415 position = matcher.start(); // don't skip bad token
2416 throw new InputMismatchException(nfe.getMessage());
2417 }
2418 }
2419
2420 // Convenience methods for scanning multi precision numbers
2421
2422 /**
2423 * Returns true if the next token in this scanner's input can be
2424 * interpreted as a {@code BigInteger} in the default radix using the
2425 * {@link #nextBigInteger} method. The scanner does not advance past any
2426 * input.
2427 *
2428 * @return true if and only if this scanner's next token is a valid
2429 * {@code BigInteger}
2430 * @throws IllegalStateException if this scanner is closed
2431 */
2432 public boolean hasNextBigInteger() {
2433 return hasNextBigInteger(defaultRadix);
2434 }
2435
2436 /**
2437 * Returns true if the next token in this scanner's input can be
2438 * interpreted as a {@code BigInteger} in the specified radix using
2439 * the {@link #nextBigInteger} method. The scanner does not advance past
2440 * any input.
2441 *
2442 * @param radix the radix used to interpret the token as an integer
2443 * @return true if and only if this scanner's next token is a valid
2444 * {@code BigInteger}
2445 * @throws IllegalStateException if this scanner is closed
2446 */
2447 public boolean hasNextBigInteger(int radix) {
2448 setRadix(radix);
2449 boolean result = hasNext(integerPattern());
2450 if (result) { // Cache it
2451 try {
2452 String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
2453 processIntegerToken(hasNextResult) :
2454 hasNextResult;
2455 typeCache = new BigInteger(s, radix);
2456 } catch (NumberFormatException nfe) {
2457 result = false;
2458 }
2459 }
2460 return result;
2461 }
2462
2463 /**
2464 * Scans the next token of the input as a {@link java.math.BigInteger
2465 * BigInteger}.
2466 *
2467 * <p> An invocation of this method of the form
2468 * {@code nextBigInteger()} behaves in exactly the same way as the
2469 * invocation {@code nextBigInteger(radix)}, where {@code radix}
2470 * is the default radix of this scanner.
2471 *
2472 * @return the {@code BigInteger} scanned from the input
2473 * @throws InputMismatchException
2474 * if the next token does not match the <i>Integer</i>
2475 * regular expression, or is out of range
2476 * @throws NoSuchElementException if the input is exhausted
2477 * @throws IllegalStateException if this scanner is closed
2478 */
2479 public BigInteger nextBigInteger() {
2480 return nextBigInteger(defaultRadix);
2481 }
2482
2483 /**
2484 * Scans the next token of the input as a {@link java.math.BigInteger
2485 * BigInteger}.
2486 *
2487 * <p> If the next token matches the <a
2488 * href="#Integer-regex"><i>Integer</i></a> regular expression defined
2489 * above then the token is converted into a {@code BigInteger} value as if
2490 * by removing all group separators, mapping non-ASCII digits into ASCII
2491 * digits via the {@link Character#digit Character.digit}, and passing the
2492 * resulting string to the {@link
2493 * java.math.BigInteger#BigInteger(java.lang.String)
2494 * BigInteger(String, int)} constructor with the specified radix.
2495 *
2496 * @param radix the radix used to interpret the token
2497 * @return the {@code BigInteger} scanned from the input
2498 * @throws InputMismatchException
2499 * if the next token does not match the <i>Integer</i>
2500 * regular expression, or is out of range
2501 * @throws NoSuchElementException if the input is exhausted
2502 * @throws IllegalStateException if this scanner is closed
2503 */
2504 public BigInteger nextBigInteger(int radix) {
2505 // Check cached result
2506 if ((typeCache != null) && (typeCache instanceof BigInteger)
2507 && this.radix == radix) {
2508 BigInteger val = (BigInteger)typeCache;
2509 useTypeCache();
2510 return val;
2511 }
2512 setRadix(radix);
2513 clearCaches();
2514 // Search for next int
2515 try {
2516 String s = next(integerPattern());
2517 if (matcher.group(SIMPLE_GROUP_INDEX) == null)
2518 s = processIntegerToken(s);
2519 return new BigInteger(s, radix);
2520 } catch (NumberFormatException nfe) {
2521 position = matcher.start(); // don't skip bad token
2522 throw new InputMismatchException(nfe.getMessage());
2523 }
2524 }
2525
2526 /**
2527 * Returns true if the next token in this scanner's input can be
2528 * interpreted as a {@code BigDecimal} using the
2529 * {@link #nextBigDecimal} method. The scanner does not advance past any
2530 * input.
2531 *
2532 * @return true if and only if this scanner's next token is a valid
2533 * {@code BigDecimal}
2534 * @throws IllegalStateException if this scanner is closed
2535 */
2536 public boolean hasNextBigDecimal() {
2537 setRadix(10);
2538 boolean result = hasNext(decimalPattern());
2539 if (result) { // Cache it
2540 try {
2541 String s = processFloatToken(hasNextResult);
2542 typeCache = new BigDecimal(s);
2543 } catch (NumberFormatException nfe) {
2544 result = false;
2545 }
2546 }
2547 return result;
2548 }
2549
2550 /**
2551 * Scans the next token of the input as a {@link java.math.BigDecimal
2552 * BigDecimal}.
2553 *
2554 * <p> If the next token matches the <a
2555 * href="#Decimal-regex"><i>Decimal</i></a> regular expression defined
2556 * above then the token is converted into a {@code BigDecimal} value as if
2557 * by removing all group separators, mapping non-ASCII digits into ASCII
2558 * digits via the {@link Character#digit Character.digit}, and passing the
2559 * resulting string to the {@link
2560 * java.math.BigDecimal#BigDecimal(java.lang.String) BigDecimal(String)}
2561 * constructor.
2562 *
2563 * @return the {@code BigDecimal} scanned from the input
2564 * @throws InputMismatchException
2565 * if the next token does not match the <i>Decimal</i>
2566 * regular expression, or is out of range
2567 * @throws NoSuchElementException if the input is exhausted
2568 * @throws IllegalStateException if this scanner is closed
2569 */
2570 public BigDecimal nextBigDecimal() {
2571 // Check cached result
2572 if ((typeCache != null) && (typeCache instanceof BigDecimal)) {
2573 BigDecimal val = (BigDecimal)typeCache;
2574 useTypeCache();
2575 return val;
2576 }
2577 setRadix(10);
2578 clearCaches();
2579 // Search for next float
2580 try {
2581 String s = processFloatToken(next(decimalPattern()));
2582 return new BigDecimal(s);
2583 } catch (NumberFormatException nfe) {
2584 position = matcher.start(); // don't skip bad token
2585 throw new InputMismatchException(nfe.getMessage());
2586 }
2587 }
2588
2589 /**
2590 * Resets this scanner.
2591 *
2592 * <p> Resetting a scanner discards all of its explicit state
2593 * information which may have been changed by invocations of {@link
2594 * #useDelimiter}, {@link #useLocale}, or {@link #useRadix}.
2595 *
2596 * <p> An invocation of this method of the form
2597 * {@code scanner.reset()} behaves in exactly the same way as the
2598 * invocation
2599 *
2600 * <blockquote><pre>{@code
2601 * scanner.useDelimiter("\\p{javaWhitespace}+")
2602 * .useLocale(Locale.getDefault(Locale.Category.FORMAT))
2603 * .useRadix(10);
2604 * }</pre></blockquote>
2605 *
2606 * @return this scanner
2607 *
2608 * @since 1.6
2609 */
2610 public Scanner reset() {
2611 delimPattern = WHITESPACE_PATTERN;
2612 useLocale(Locale.getDefault(Locale.Category.FORMAT));
2613 useRadix(10);
2614 clearCaches();
2615 return this;
2616 }
2617 }
|