001package stdlib;
002/* ***********************************************************************
003 *  Compilation:  javac In.java
004 *  Execution:    java In   (basic test --- see source for required files)
005 *
006 *  Reads in data of various types from standard input, files, and URLs.
007 *
008 *************************************************************************/
009
010import java.io.BufferedInputStream;
011import java.io.File;
012import java.io.IOException;
013import java.io.InputStream;
014import java.net.URL;
015import java.net.URLConnection;
016import java.util.Scanner;
017import java.util.regex.Pattern;
018
019/**
020 *  <i>Input</i>. This class provides methods for reading strings
021 *  and numbers from standard input, file input, URLs, and sockets.
022 *  <p>
023 *  The Locale used is: language = English, country = US. This is consistent
024 *  with the formatting conventions with Java floating-point literals,
025 *  command-line arguments (via {@link Double#parseDouble(String)})
026 *  and standard output.
027 *  <p>
028 *  For additional documentation, see
029 *  <a href="http://introcs.cs.princeton.edu/31datatype">Section 3.1</a> of
030 *  <i>Introduction to Programming in Java: An Interdisciplinary Approach</i>
031 *  by Robert Sedgewick and Kevin Wayne.
032 *  <p>
033 *  Like {@link Scanner}, reading a token also consumes preceding Java
034 *  whitespace, reading a full line consumes
035 *  the following end-of-line delimeter, while reading a character consumes
036 *  nothing extra.
037 *  <p>
038 *  Whitespace is defined in {@link Character#isWhitespace(char)}. Newlines
039 *  consist of \n, \r, \r\n, and Unicode hex code points 0x2028, 0x2029, 0x0085;
040 *  see <a href="http://www.docjar.com/html/api/java/util/Scanner.java.html">
041 *  {@code Scanner.java}</a> (NB: Java 6u23 and earlier uses only \r, \r, \r\n).
042 */
043public final class In {
044
045        private Scanner scanner;
046
047        /* * begin: section (1 of 2) of code duplicated from In to StdIn */
048
049        // assume Unicode UTF-8 encoding
050        private static final String charsetName = "UTF-8";
051
052        // assume language = English, country = US for consistency with System.out.
053        private static final java.util.Locale usLocale =
054                        new java.util.Locale("en", "US");
055
056        // the default token separator; we maintain the invariant that this value
057        // is held by the scanner's delimiter between calls
058        private static final Pattern WHITESPACE_PATTERN
059        = Pattern.compile("\\p{javaWhitespace}+");
060
061        // makes whitespace characters significant
062        private static final Pattern EMPTY_PATTERN
063        = Pattern.compile("");
064
065        // used to read the entire input. source:
066        // http://weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner_1.html
067        private static final Pattern EVERYTHING_PATTERN
068        = Pattern.compile("\\A");
069
070        /* * end: section (1 of 2) of code duplicated from In to StdIn */
071
072        /**
073         * Create an input stream from standard input.
074         */
075        public In() {
076                scanner = new Scanner(new BufferedInputStream(System.in), charsetName);
077                scanner.useLocale(usLocale);
078        }
079
080        /**
081         * Create an input stream from a socket.
082         */
083        public In(java.net.Socket socket) {
084                try {
085                        InputStream is = socket.getInputStream();
086                        scanner = new Scanner(new BufferedInputStream(is), charsetName);
087                        scanner.useLocale(usLocale);
088                }
089                catch (IOException ioe) {
090                        System.err.println("Could not open " + socket);
091                }
092        }
093
094        /**
095         * Create an input stream from a URL.
096         */
097        public In(URL url) {
098                try {
099                        URLConnection site = url.openConnection();
100                        InputStream is     = site.getInputStream();
101                        scanner            = new Scanner(new BufferedInputStream(is), charsetName);
102                        scanner.useLocale(usLocale);
103                }
104                catch (IOException ioe) {
105                        System.err.println("Could not open " + url);
106                }
107        }
108
109        /**
110         * Create an input stream from a file.
111         */
112        public In(File file) {
113                try {
114                        scanner = new Scanner(file, charsetName);
115                        scanner.useLocale(usLocale);
116                }
117                catch (IOException ioe) {
118                        System.err.println("Could not open " + file);
119                }
120        }
121
122
123        /**
124         * Create an input stream from a filename or web page name.
125         */
126        public In(String s) {
127                try {
128                        // first try to read file from local file system
129                        File file = new File(s);
130                        if (file.exists()) {
131                                scanner = new Scanner(file, charsetName);
132                                scanner.useLocale(usLocale);
133                                return;
134                        }
135
136                        // next try for files included in jar
137                        URL url = getClass().getResource(s);
138
139                        // or URL from web
140                        if (url == null) { url = new URL(s); }
141
142                        URLConnection site = url.openConnection();
143                        InputStream is     = site.getInputStream();
144                        scanner            = new Scanner(new BufferedInputStream(is), charsetName);
145                        scanner.useLocale(usLocale);
146                }
147                catch (IOException ioe) {
148                        System.err.println("Could not open " + s);
149                }
150        }
151
152        /**
153         * Create an input stream from a given Scanner source; use with
154         * {@code new Scanner(String)} to read from a string.
155         * <p>
156         * Note that this does not create a defensive copy, so the
157         * scanner will be mutated as you read on.
158         */
159        public In(Scanner scanner) {
160                this.scanner = scanner;
161        }
162
163        /**
164         * Does the input stream exist?
165         */
166        public boolean exists()  {
167                return scanner != null;
168        }
169
170        /* * begin: section (2 of 2) of code duplicated from In to StdIn,
171         *  with all methods changed from "public" to "public static" ***/
172
173        /**
174         * Is the input empty (except possibly for whitespace)? Use this
175         * to know whether the next call to {@link #readString()},
176         * {@link #readDouble()}, etc will succeed.
177         */
178        public boolean isEmpty() {
179                return !scanner.hasNext();
180        }
181
182        /**
183         * Does the input have a next line? Use this to know whether the
184         * next call to {@link #readLine()} will succeed. <p> Functionally
185         * equivalent to {@link #hasNextChar()}.
186         */
187        public boolean hasNextLine() {
188                return scanner.hasNextLine();
189        }
190
191        /**
192         * Is the input empty (including whitespace)? Use this to know
193         * whether the next call to {@link #readChar()} will succeed. <p> Functionally
194         * equivalent to {@link #hasNextLine()}.
195         */
196        public boolean hasNextChar() {
197                scanner.useDelimiter(EMPTY_PATTERN);
198                boolean result = scanner.hasNext();
199                scanner.useDelimiter(WHITESPACE_PATTERN);
200                return result;
201        }
202
203
204        /**
205         * Read and return the next line.
206         */
207        public String readLine() {
208                String line;
209                try                 { line = scanner.nextLine(); }
210                catch (Exception e) { line = null;               }
211                return line;
212        }
213
214        /**
215         * Read and return the next character.
216         */
217        public char readChar() {
218                scanner.useDelimiter(EMPTY_PATTERN);
219                String ch = scanner.next();
220                assert (ch.length() == 1) : "Internal (Std)In.readChar() error!"
221                + " Please contact the authors.";
222                scanner.useDelimiter(WHITESPACE_PATTERN);
223                return ch.charAt(0);
224        }
225
226
227        /**
228         * Read and return the remainder of the input as a string.
229         */
230        public String readAll() {
231                if (!scanner.hasNextLine())
232                        return "";
233
234                String result = scanner.useDelimiter(EVERYTHING_PATTERN).next();
235                // not that important to reset delimeter, since now scanner is empty
236                scanner.useDelimiter(WHITESPACE_PATTERN); // but let's do it anyway
237                return result;
238        }
239
240
241        /**
242         * Read and return the next string.
243         */
244        public String readString() {
245                return scanner.next();
246        }
247
248        /**
249         * Read and return the next int.
250         */
251        public int readInt() {
252                return scanner.nextInt();
253        }
254
255        /**
256         * Read and return the next double.
257         */
258        public double readDouble() {
259                return scanner.nextDouble();
260        }
261
262        /**
263         * Read and return the next float.
264         */
265        public float readFloat() {
266                return scanner.nextFloat();
267        }
268
269        /**
270         * Read and return the next long.
271         */
272        public long readLong() {
273                return scanner.nextLong();
274        }
275
276        /**
277         * Read and return the next short.
278         */
279        public short readShort() {
280                return scanner.nextShort();
281        }
282
283        /**
284         * Read and return the next byte.
285         */
286        public byte readByte() {
287                return scanner.nextByte();
288        }
289
290        /**
291         * Read and return the next boolean, allowing case-insensitive
292         * "true" or "1" for true, and "false" or "0" for false.
293         */
294        public boolean readBoolean() {
295                String s = readString();
296                if (s.equalsIgnoreCase("true"))  return true;
297                if (s.equalsIgnoreCase("false")) return false;
298                if (s.equals("1"))               return true;
299                if (s.equals("0"))               return false;
300                throw new java.util.InputMismatchException();
301        }
302
303        /**
304         * Read all strings until the end of input is reached, and return them.
305         */
306        public String[] readAllStrings() {
307                // we could use readAll.trim().split(), but that's not consistent
308                // since trim() uses characters 0x00..0x20 as whitespace
309                String[] tokens = WHITESPACE_PATTERN.split(readAll());
310                if (tokens.length == 0 || tokens[0].length() > 0)
311                        return tokens;
312                String[] decapitokens = new String[tokens.length-1];
313                for (int i = 0; i < tokens.length-1; i++)
314                        decapitokens[i] = tokens[i+1];
315                return decapitokens;
316        }
317
318        /**
319         * Read all ints until the end of input is reached, and return them.
320         */
321        public int[] readAllInts() {
322                String[] fields = readAllStrings();
323                int[] vals = new int[fields.length];
324                for (int i = 0; i < fields.length; i++)
325                        vals[i] = Integer.parseInt(fields[i]);
326                return vals;
327        }
328
329        /**
330         * Read all doubles until the end of input is reached, and return them.
331         */
332        public double[] readAllDoubles() {
333                String[] fields = readAllStrings();
334                double[] vals = new double[fields.length];
335                for (int i = 0; i < fields.length; i++)
336                        vals[i] = Double.parseDouble(fields[i]);
337                return vals;
338        }
339
340        /* * end: section (2 of 2) of code duplicated from In to StdIn */
341
342        /**
343         * Close the input stream.
344         */
345        public void close() {
346                scanner.close();
347        }
348
349        /**
350         * Reads all ints from a file
351         * @deprecated Clearer to use
352         * {@code new In(filename)}.{@link #readAllInts()}
353         */
354        @Deprecated public static int[] readInts(String filename) {
355                return new In(filename).readAllInts();
356        }
357
358        /**
359         * Reads all doubles from a file
360         * @deprecated Clearer to use
361         * {@code new In(filename)}.{@link #readAllDoubles()}
362         */
363        @Deprecated public static double[] readDoubles(String filename) {
364                return new In(filename).readAllDoubles();
365        }
366
367        /**
368         * Reads all strings from a file
369         * @deprecated Clearer to use
370         * {@code new In(filename)}.{@link #readAllStrings()}
371         */
372        @Deprecated public static String[] readStrings(String filename) {
373                return new In(filename).readAllStrings();
374        }
375
376        /**
377         * Reads all ints from stdin
378         * @deprecated Clearer to use {@link StdIn#readAllInts()}
379         */
380        @Deprecated public static int[] readInts() {
381                return new In().readAllInts();
382        }
383
384        /**
385         * Reads all doubles from stdin
386         * @deprecated Clearer to use {@link StdIn#readAllDoubles()}
387         */
388        @Deprecated public static double[] readDoubles() {
389                return new In().readAllDoubles();
390        }
391
392        /**
393         * Reads all strings from stdin
394         * @deprecated Clearer to use {@link StdIn#readAllStrings()}
395         */
396        @Deprecated public static String[] readStrings() {
397                return new In().readAllStrings();
398        }
399
400        /**
401         * Return true if the next value from the input stream can be interpreted as an int
402         */
403        public boolean hasNextInt() {
404                return scanner.hasNextInt();
405        }
406
407        /**
408         * Return true if the next value from the input stream can be interpreted as an double
409         */
410        public boolean hasNextDouble() {
411                return scanner.hasNextDouble();
412        }
413
414        /**
415         * Return true if the next value from the input stream can be interpreted as an float
416         */
417        public boolean hasNextFloat() {
418                return scanner.hasNextFloat();
419        }
420
421        /**
422         * Return true if the next value from the input stream can be interpreted as a long
423         */
424        public boolean hasNextLong() {
425                return scanner.hasNextLong();
426        }
427
428        /**
429         * Return true if the next value from the input stream can be interpreted as a byte
430         */
431        public boolean hasNextByte() {
432                return scanner.hasNextByte();
433        }
434
435        /**
436         * Test client.
437         */
438        public static void main(String[] args) {
439                In in;
440                String urlName = "http://introcs.cs.princeton.edu/stdlib/InTest.txt";
441
442                // read from a URL
443                System.out.println("readAll() from URL " + urlName);
444                System.out.println("---------------------------------------------------------------------------");
445                try {
446                        in = new In(urlName);
447                        System.out.println(in.readAll());
448                }
449                catch (Exception e) { System.out.println(e); }
450                System.out.println();
451
452                // read one line at a time from URL
453                System.out.println("readLine() from URL " + urlName);
454                System.out.println("---------------------------------------------------------------------------");
455                try {
456                        in = new In(urlName);
457                        while (!in.isEmpty()) {
458                                String s = in.readLine();
459                                System.out.println(s);
460                        }
461                }
462                catch (Exception e) { System.out.println(e); }
463                System.out.println();
464
465                // read one string at a time from URL
466                System.out.println("readString() from URL " + urlName);
467                System.out.println("---------------------------------------------------------------------------");
468                try {
469                        in = new In(urlName);
470                        while (!in.isEmpty()) {
471                                String s = in.readString();
472                                System.out.println(s);
473                        }
474                }
475                catch (Exception e) { System.out.println(e); }
476                System.out.println();
477
478
479                // read one line at a time from file in current directory
480                System.out.println("readLine() from current directory");
481                System.out.println("---------------------------------------------------------------------------");
482                try {
483                        in = new In("./InTest.txt");
484                        while (!in.isEmpty()) {
485                                String s = in.readLine();
486                                System.out.println(s);
487                        }
488                }
489                catch (Exception e) { System.out.println(e); }
490                System.out.println();
491
492
493                // read one line at a time from file using relative path
494                System.out.println("readLine() from relative path");
495                System.out.println("---------------------------------------------------------------------------");
496                try {
497                        in = new In("../stdlib/InTest.txt");
498                        while (!in.isEmpty()) {
499                                String s = in.readLine();
500                                System.out.println(s);
501                        }
502                }
503                catch (Exception e) { System.out.println(e); }
504                System.out.println();
505
506                // read one char at a time
507                System.out.println("readChar() from file");
508                System.out.println("---------------------------------------------------------------------------");
509                try {
510                        in = new In("InTest.txt");
511                        while (!in.isEmpty()) {
512                                char c = in.readChar();
513                                System.out.print(c);
514                        }
515                }
516                catch (Exception e) { System.out.println(e); }
517                System.out.println();
518                System.out.println();
519
520                // read one line at a time from absolute OS X / Linux path
521                System.out.println("readLine() from absolute OS X / Linux path");
522                System.out.println("---------------------------------------------------------------------------");
523                in = new In("/n/fs/introcs/www/java/stdlib/InTest.txt");
524                try {
525                        while (!in.isEmpty()) {
526                                String s = in.readLine();
527                                System.out.println(s);
528                        }
529                }
530                catch (Exception e) { System.out.println(e); }
531                System.out.println();
532
533
534                // read one line at a time from absolute Windows path
535                System.out.println("readLine() from absolute Windows path");
536                System.out.println("---------------------------------------------------------------------------");
537                try {
538                        in = new In("G:\\www\\introcs\\stdlib\\InTest.txt");
539                        while (!in.isEmpty()) {
540                                String s = in.readLine();
541                                System.out.println(s);
542                        }
543                        System.out.println();
544                }
545                catch (Exception e) { System.out.println(e); }
546                System.out.println();
547
548        }
549
550}