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}