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}