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