View Javadoc
1 /* ------------------------------------------------------------------- 2 * Java source file for the class StringTokenReader 3 * 4 * Copyright (c), 2002, Masahiro Takatsuka. 5 * All Rights Researved. 6 * 7 * Original Author: Masahiro Takatsuka (masa@jbeans.net) 8 * $Author: takatsukam $ 9 * 10 * $Date: 2003/07/25 04:51:46 $ 11 * 12 * $Id: StringTokenReader.java,v 1.1.1.1 2003/07/25 04:51:46 takatsukam Exp $ 13 * 14 * Reference: Document no: 15 * ___ ___ 16 * 17 * To Do: 18 * ___ 19 * 20 ------------------------------------------------------------------- */ 21 22 /* --------------------------- Package ---------------------------- */ 23 package net.jbeans.io; 24 25 /* ------------------ Import classes (packages) ------------------- *//package-summary/html">color="#329900"> ------------------ Import classes (packages) ------------------- *//package-summary.html">color="#329900">/* ------------------ Import classes (packages) ------------------- *//package-summary.html">color="#329900"> ------------------ Import classes (packages) ------------------- */ 26 import java.io.*; 27 import java.util.*; 28 29 /*==================================================================== 30 Implementation of class StringTokenReader 31 ====================================================================*/ 32 /*** 33 * The -string reader class allows an application to read tokens 34 * as well as single characters from a string. The tokenization method 35 * is the same one used by <code>StringTokenizer</code>. 36 * The <code>StringTokenReader</code> does not recognize identifiers, numbers, 37 * quoted strings and skip comments. 38 * <p> 39 * Delimiters can be set at creation time as well as on a per-token basis. 40 * <p> 41 * The <code>StringTokenReader</code> behaves in one of two ways 42 * (same as java.util.StringTokenizer), depending 43 * on whether it was created with the <code>returnTokens</code> flag 44 * having the value <code>true</code> or <code>false</code>: see more detail 45 * in <code>java.util.StringTokenizer</code>. 46 * <p> 47 * The following is one example of the use of the string reader. The code: 48 * <blockquote><pre> 49 * StringTokenReader sr = new StringTokenReader("this is a test 1 2 3.4"); 50 * while (sr.hasMoreTokens()) { 51 * println(sr.nextToken()); 52 * } 53 * </pre></blockquote> 54 * <p> 55 * prints the following output: 56 * <blockquote><pre> 57 * this 58 * is 59 * a 60 * test 61 * 1 62 * 2 63 * 3.4 64 * </pre></blockquote> 65 * or 66 * <blockquote><pre> 67 * StringTokenReader sr = new StringTokenReader("this is a test 1 2 3.4"); 68 * println(sr.nextToken()); 69 * println(sr.nextToken()); 70 * println(sr.nextToken()); 71 * println(sr.nextToken()); 72 * println(sr.readInt()); 73 * println(sr.readInt()); 74 * println(sr.readFloat()); 75 * </pre></blockquote> 76 * <p> 77 * prints the following output: 78 * <blockquote><pre> 79 * this 80 * is 81 * a 82 * test 83 * 1 84 * 2 85 * 3.4 86 * </pre></blockquote> 87 * 88 * @version $Revision: 1.1.1.1 $ 89 * @author Masahiro Takatsuka (masa@jbeans.net) 90 * @see Reader 91 * @see Enumeration 92 */ 93 94 public final class StringTokenReader extends Reader implements Enumeration { 95 private int currentPosition; 96 private int maxPosition; 97 private String str; 98 private String delimiters; 99 private boolean retTokens; 100 private int mark; 101 private String quotes; // 1999-Oct-18 102 103 /*** 104 * Constructs a M-string reader for the specified string. The set of 105 * delimiters is specified in the <code>delim</code> argument. 106 * <p> 107 * If the <code>returnTokens</code> flag is <code>true</code>, then 108 * the delimiter characters are also returned as tokens. 109 * 110 * @param str a string to be parsed. 111 * @param delim the delimiters. 112 * @param quotes quotation characters.// 1999-Oct-18 113 * @param returnTokens flag indicating whether to return the delimiters 114 * as tokens. 115 */ 116 public StringTokenReader(String str, String delim, String quotes, boolean returnTokens) { 117 super(); 118 this.currentPosition = 0; 119 this.str = str; 120 this.maxPosition = (this.str !=null)?this.str.length():0; 121 this.delimiters = (delim == null) ? " \t\n\r\f" : delim; 122 this.quotes = quotes; // 1999-Oct-18 123 this.retTokens = returnTokens; 124 this.mark = 0; 125 } 126 127 /*** 128 * Constructs a M-string reader for the specified string. The set of 129 * delimiters is specified in the <code>delim</code> argument. 130 * <p> 131 * If the <code>returnTokens</code> flag is <code>true</code>, then 132 * the delimiter characters are also returned as tokens. 133 * 134 * @param str a string to be parsed. 135 * @param delim the delimiters. 136 * @param returnTokens flag indicating whether to return the delimiters 137 * as tokens. 138 */ 139 public StringTokenReader(String str, String delim, boolean returnTokens) { 140 this(str, delim, "\"\'", returnTokens); 141 } 142 143 /*** 144 * Constructs a M-string reader for the specified string. The set of 145 * delimiters is specified in the <code>delim</code> argument. 146 * 147 * @param str a string to be parsed. 148 * @param delim the delimiters. 149 */ 150 public StringTokenReader(String str, String delim) { 151 this(str, delim, false); 152 } 153 154 /*** 155 * Constructs a M-string reader for the specified string. The following 156 * characters are used as the default delimiter set: 157 * <code>"\t\n\r\f"</code>: the space character, the tab 158 * character, the newline character, the carriage-return character, 159 * and the form-feed character. 160 * 161 * @param str a string to be parsed. 162 */ 163 public StringTokenReader(String str) { 164 this(str, " \t\n\r\f", false); 165 } 166 167 /*** 168 * Skips delimiters. 169 */ 170 private void skipDelimiters() { 171 if (!this.retTokens) { 172 while ((this.currentPosition < this.maxPosition) && 173 (this.delimiters.indexOf(this.str.charAt(this.currentPosition)) >= 0)) { 174 this.currentPosition++; 175 } 176 } 177 } 178 179 /*** 180 * Returns <tt>true</tt> if there are more tokens available. 181 * If this method returns <tt>true</tt>, then a subsequent call to 182 * <tt>nextToken</tt> or <tt>readToken</tt> with no argument will 183 * successfully return a token. 184 * 185 * @return <code>true</code> if and only if there is at least one token 186 * in the string after the current position; <code>false</code> 187 * otherwise. 188 */ 189 public final boolean hasMoreTokens() { 190 skipDelimiters(); 191 return (this.currentPosition < this.maxPosition); 192 } 193 194 /*** 195 * Returns the rest of tokens in the string. 196 * 197 * @return the rest of tokens in the string. 198 * @exception NoSuchElementException if there are no more tokens. 199 */ 200 public final String restOfTokens() { 201 skipDelimiters(); 202 if (this.currentPosition >= this.maxPosition) { 203 throw new NoSuchElementException(); 204 } 205 return this.str.substring(this.currentPosition); 206 } 207 208 /*** 209 * Returns the next token. 210 * 211 * @return the next token. 212 * @exception NoSuchElementException if there are no more tokens. 213 */ 214 public final String nextToken() { 215 skipDelimiters(); 216 217 if (this.currentPosition >= this.maxPosition) { 218 throw new NoSuchElementException(); 219 } 220 221 int start = this.currentPosition; 222 while ((this.currentPosition < this.maxPosition) && 223 (this.delimiters.indexOf(this.str.charAt(this.currentPosition)) < 0)) { 224 this.currentPosition++; 225 } 226 if (this.retTokens && (start == this.currentPosition) && 227 (this.delimiters.indexOf(this.str.charAt(this.currentPosition)) >= 0)) { 228 this.currentPosition++; 229 } 230 return this.str.substring(start, this.currentPosition); 231 } 232 233 /*** 234 * Returns the next token. First, delimiters specified by 235 * <tt>delim</tt> is set as the new delimiters. Then the next token 236 * in the string after the current position is returned. 237 * The new delimiter set remains the default after this call. 238 * 239 * @param delim the new delimiters. 240 * @return the next token, after switching to the new delimiter set. 241 * @exception NoSuchElementException if there are no more tokens. 242 */ 243 public final String nextToken(String delim) { 244 this.delimiters = delim; 245 return nextToken(); 246 } 247 248 /*** 249 * Returns the same value as the <code>hasMoreTokens</code> 250 * method. It exists so that this class can implement the 251 * <code>Enumeration</code> interface. 252 * 253 * @return <code>true</code> if there are more tokens; 254 * <code>false</code> otherwise. 255 * @see #hasMoreTokens() 256 */ 257 public final boolean hasMoreElements() { 258 return hasMoreTokens(); 259 } 260 261 /*** 262 * Returns the same value as the <code>nextToken</code> method, 263 * except that its declared return value is <code>Object</code> rather than 264 * <code>String</code>. It exists so that this class can implement the 265 * <code>Enumeration</code> interface. 266 * 267 * @return the next token in the string. 268 * @exception NoSuchElementException if there are no more tokens in this 269 * tokenizer's string. 270 * @see #nextToken() 271 */ 272 public final Object nextElement() { 273 return nextToken(); 274 } 275 276 /*** 277 * Calculates the number of tokens in the string. 278 * The current position is not advanced. 279 * 280 * @return the number of tokens remaining in the string using the current 281 * delimiter set. 282 */ 283 public final int countTokens() { 284 int count = 0; 285 int currpos = this.currentPosition; 286 287 while (currpos < this.maxPosition) { 288 if (!this.retTokens) { // skip delimiters. 289 while ((currpos < this.maxPosition) && 290 (this.delimiters.indexOf(this.str.charAt(currpos)) >= 0)) { 291 currpos++; 292 } 293 } 294 295 if (currpos >= this.maxPosition) { 296 break; 297 } 298 299 int start = currpos; 300 while ((currpos < this.maxPosition) && 301 (this.delimiters.indexOf(this.str.charAt(currpos)) < 0)) { 302 currpos++; 303 } 304 if (this.retTokens && (start == currpos) && 305 (this.delimiters.indexOf(this.str.charAt(currpos)) >= 0)) { 306 currpos++; 307 } 308 count++; 309 310 } 311 return count; 312 } 313 314 /*** 315 * Resets a M-string reader for the specified string. The set of 316 * delimiters is specified in the <code>delim</code> argument. 317 * <p> 318 * If the <code>returnTokens</code> flag is <code>true</code>, then 319 * the delimiter characters are also returned as tokens. 320 * 321 * @param str a string to be parsed. 322 * @param delim the delimiters. 323 * @param returnTokens flag indicating whether to return the delimiters 324 * as tokens. 325 */ 326 public final void reset(String str, String delim, boolean returnTokens) { 327 this.currentPosition = 0; 328 this.str = str; 329 this.maxPosition = (this.str !=null)?this.str.length():0; 330 this.delimiters = delim; 331 this.retTokens = returnTokens; 332 } 333 334 /*** 335 * Constructs a M-string reader for the specified string. The set of 336 * delimiters is specified in the <code>delim</code> argument. 337 * 338 * @param str a string to be parsed. 339 * @param delim the delimiters. 340 */ 341 public final void reset(String str, String delim) { 342 reset(str, delim, false); 343 } 344 345 /*** 346 * Constructs a M-string reader for the specified string. The following 347 * characters are used as the default delimiter set: 348 * <code>"\t\n\r\f"</code>: the space character, the tab 349 * character, the newline character, the carriage-return character, 350 * and the form-feed character. 351 * 352 * @param str a string to be parsed. 353 */ 354 public final void reset(String str) { 355 reset(str, " \t\n\r\f", false); 356 } 357 358 /*** 359 * Read characters into a portion of an array. 360 * 361 * @param cbuf Destination buffer 362 * @param off Offset at which to start writing characters 363 * @param len Maximum number of characters to read 364 * @return The number of characters read, or -1 if the end of the 365 * stream has been reached 366 * 367 * @exception IOException If an I/O error occurs 368 */ 369 public final int read(char cbuf[], int off, int len) { 370 skipDelimiters(); 371 372 if (this.currentPosition >= this.maxPosition) { 373 return -1; // the end of the stream has been reached. 374 // throw new NoSuchElementException(); 375 } 376 377 int n = Math.min(this.maxPosition - this.currentPosition, len); 378 this.str.getChars(this.currentPosition, this.currentPosition + n, cbuf, off); 379 this.currentPosition += n; 380 return n; 381 } 382 383 /*** 384 * Read a single character. This method will block until a character is 385 * available, an I/O error occurs, or the end of the stream is reached. 386 * 387 * <p> Subclasses that intend to support efficient single-character input 388 * should override this method. 389 * 390 * @return The character read, as an integer in the range 0 to 16383 391 * (<tt>0x00-0xffff</tt>), or -1 if the end of the stream has 392 * been reached 393 */ 394 public final int read() { 395 char cb[] = new char[1]; 396 if (read(cb, 0, 1) == -1) 397 return -1; 398 else 399 return cb[0]; 400 } 401 402 /*** 403 * Read characters into an array. This method will block until some input 404 * is available, an I/O error occurs, or the end of the stream is reached. 405 * 406 * @param cbuf Destination buffer 407 * 408 * @return The number of bytes read, or -1 if the end of the stream 409 * has been reached 410 */ 411 public final int read(char cbuf[]) { 412 return read(cbuf, 0, cbuf.length); 413 } 414 415 /*** 416 * Tell whether this stream is ready to be read. String readers are 417 * always ready to be read. 418 */ 419 public final boolean ready() { 420 return (this.str != null)?true:false; 421 } 422 423 /*** 424 * Tell whether this stream supports the mark() operation, which it does. 425 */ 426 public final boolean markSupported() { 427 return true; 428 } 429 430 /*** 431 * Mark the present position in the stream. Subsequent calls to reset() 432 * will reposition the stream to this point. 433 * 434 * @param readAheadLimit Limit on the number of characters that may be 435 * read while still preserving the mark. Because 436 * the stream's input comes from a string, there 437 * is no actual limit, so this argument is ignored. 438 * 439 * @exception IOException If an I/O error occurs 440 */ 441 public final void mark(int readAheadLimit) throws IOException { 442 this.mark = this.currentPosition; 443 } 444 445 /*** 446 * Reset the stream to the most recent mark, or to the beginning of the 447 * string if it has never been marked. 448 * 449 * @exception IOException If an I/O error occurs 450 */ 451 public final void reset() throws IOException { 452 this.currentPosition = this.mark; 453 } 454 455 /*** 456 * Close the stream. 457 */ 458 public final void close() { 459 this.str = null; 460 } 461 462 /*** 463 * Read one token as a string. 464 * 465 * @return A String containing the string, or null if the end of the 466 * stream has been reached. 467 */ 468 public final String readToken() { 469 return nextToken(); 470 } 471 472 /*** 473 * Returns the next token in this string tokenizer's string. First, 474 * the set of characters considered to be delimiters by this 475 * <tt>StringTokenizer</tt> object is changed to be the characters in 476 * the string <tt>delim</tt>. Then the next token in the string 477 * after the current position is returned. The current position is 478 * advanced beyond the recognized token. The new delimiter set 479 * remains the default after this call. 480 * 481 * @param delim the new delimiters. 482 * @return the next token, after switching to the new delimiter set. 483 * @exception NoSuchElementException if there are no more tokens in this 484 * tokenizer's string. 485 */ 486 public final String readToken(String delim) { 487 return nextToken(delim); 488 } 489 490 /*** 491 * Reads a <code>boolean</code> from this data input stream. This 492 * method reads a single byte from the underlying input stream. A 493 * value of <code>0</code> represents <code>false</code>. Any other 494 * value represents <code>true</code>. This method blocks until 495 * either the byte is read, the end of the stream is detected, or an 496 * exception is thrown. 497 * 498 * @return the <code>boolean</code> value read. 499 */ 500 public final boolean readBoolean() { 501 return (Boolean.valueOf(nextToken())).booleanValue(); 502 } 503 504 /*** 505 * Reads a signed 8-bit value from this data input stream. This 506 * method reads a byte from the underlying input stream. If the byte 507 * read is <code>b</code>, where 508 * 0 <= <code>b</code> <= 255, then the 509 * result is: 510 * <ul><code> 511 * (byte)(b) 512 * </code></ul> 513 * <p> 514 * This method blocks until either the byte is read, the end of the 515 * stream is detected, or an exception is thrown. 516 * 517 * @return the next byte of this input stream as a signed 8-bit 518 * <code>byte</code>. 519 */ 520 public final byte readByte() { 521 return Byte.parseByte(nextToken()); 522 } 523 524 /*** 525 * Reads a signed 16-bit number from this data input stream. The 526 * method reads two bytes from the underlying input stream. If the two 527 * bytes read, in order, are <code>b1</code> and <code>b2</code>, 528 * where each of the two values is between <code>0</code> and 529 * <code>255</code>, inclusive, then the result is equal to: 530 * <ul><code> 531 * (short)((b1 << 8) | b2) 532 * </code></ul> 533 * <p> 534 * This method blocks until the two bytes are read, the end of the 535 * stream is detected, or an exception is thrown. 536 * 537 * @return the next two bytes of this input stream, interpreted as a 538 * signed 16-bit number. 539 */ 540 public final short readShort() { 541 return Short.parseShort(nextToken()); 542 } 543 544 /*** 545 * Reads a Unicode character from this data input stream. This 546 * method reads two bytes from the underlying input stream. If the 547 * bytes read, in order, are <code>b1</code> and <code>b2</code>, 548 * where 0 <= <code>b1</code>, 549 * <code>b1</code> <= 255, then the result is equal to: 550 * <ul><code> 551 * (char)((b1 << 8) | b2) 552 * </code></ul> 553 * <p> 554 * This method blocks until either the two bytes are read, the end of 555 * the stream is detected, or an exception is thrown. 556 * 557 * @return the next two bytes of this input stream as a Unicode 558 * character. 559 */ 560 public final char readChar() { 561 int ch1 = read(); 562 int ch2 = read(); 563 if ((ch1 | ch2) < 0) 564 throw new NoSuchElementException(); 565 return (char)((ch1 << 8) + (ch2 << 0)); 566 } 567 568 /*** 569 * Reads a signed 32-bit integer from this data input stream. This 570 * method reads four bytes from the underlying input stream. If the 571 * bytes read, in order, are <code>b1</code>, <code>b2</code>, 572 * <code>b3</code>, and <code>b4</code>, where 573 * 0 <= <code>b1</code>, <code>b2</code>, 574 * <code>b3</code>, <code>b4</code> <= 255, then the 575 * result is equal to: 576 * <ul><code> 577 * (b1 << 24) | (b2 << 16) + (b3 << 8) +b4 578 * </code></ul> 579 * <p> 580 * This method blocks until the four bytes are read, the end of the 581 * stream is detected, or an exception is thrown. 582 * 583 * @return the next four bytes of this input stream, interpreted as an 584 * <code>int</code>. 585 */ 586 public final int readInt() { 587 return Integer.parseInt(nextToken()); 588 } 589 590 /*** 591 * Reads a signed 64-bit integer from this data input stream. This 592 * method reads eight bytes from the underlying input stream. If the 593 * bytes read, in order, are <code>b1</code>, <code>b2</code>, 594 * <code>b3</code>, <code>b4</code>, <code>b5</code>, 595 * <code>b6</code>, <code>b7</code>, and <code>b8</code>, where 596 * <ul><code> 597 * 0 <= b1, b2, b3, b4, b5, b6, b7, b8 <= 255, 598 * </code></ul> 599 * <p> 600 * then the result is equal to: 601 * <p><blockquote><pre> 602 * ((long)b1 << 56) + ((long)b2 << 48) + 603 * ((long)b3 << 40) + ((long)b4 << 32) + 604 * ((long)b5 << 24) + (b6 << 16) + 605 * (b7 << 8) + b8 606 * </pre></blockquote> 607 * <p> 608 * This method blocks until the eight bytes are read, the end of the 609 * stream is detected, or an exception is thrown. 610 * 611 * @return the next eight bytes of this input stream, interpreted as a 612 * <code>long</code>. 613 */ 614 public final long readLong() throws IOException { 615 return Long.parseLong(nextToken()); 616 } 617 618 /*** 619 * Reads a <code>float</code> from this data input stream. This 620 * method reads an <code>int</code> value as if by the 621 * <code>readInt</code> method and then converts that 622 * <code>int</code> to a <code>float</code> using the 623 * <code>intBitsToFloat</code> method in class <code>Float</code>. 624 * This method blocks until the four bytes are read, the end of the 625 * stream is detected, or an exception is thrown. 626 * 627 * @return the next four bytes of this input stream, interpreted as a 628 * <code>float</code>. 629 */ 630 public final float readFloat() { 631 return Float.parseFloat(nextToken()); 632 } 633 634 /*** 635 * Reads a <code>double</code> from this data input stream. This 636 * method reads a <code>long</code> value as if by the 637 * <code>readLong</code> method and then converts that 638 * <code>long</code> to a <code>double</code> using the 639 * <code>longBitsToDouble</code> method in class <code>Double</code>. 640 * <p> 641 * This method blocks until the eight bytes are read, the end of the 642 * stream is detected, or an exception is thrown. 643 * 644 * @return the next eight bytes of this input stream, interpreted as a 645 * <code>double</code>. 646 */ 647 public final double readDouble() { 648 return Double.parseDouble(nextToken()); 649 } 650 }

This page was automatically generated by Maven