StringUtil.java |
1 /** 2 * Distribution License: 3 * JSword is free software; you can redistribute it and/or modify it under 4 * the terms of the GNU Lesser General Public License, version 2.1 or later 5 * as published by the Free Software Foundation. This program is distributed 6 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even 7 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 * See the GNU Lesser General Public License for more details. 9 * 10 * The License is available on the internet at: 11 * http://www.gnu.org/copyleft/lgpl.html 12 * or by writing to: 13 * Free Software Foundation, Inc. 14 * 59 Temple Place - Suite 330 15 * Boston, MA 02111-1307, USA 16 * 17 * © CrossWire Bible Society, 2005 - 2016 18 * 19 */ 20 package org.crosswire.common.util; 21 22 import java.io.BufferedReader; 23 import java.io.IOException; 24 import java.io.Reader; 25 26 /** 27 * A generic class of String utilities. 28 * 29 * @see gnu.lgpl.License The GNU Lesser General Public License for details. 30 * @author Joe Walker 31 */ 32 public final class StringUtil { 33 /** 34 * Prevent instantiation 35 */ 36 private StringUtil() { 37 } 38 39 /** 40 * The newline character 41 */ 42 public static final String NEWLINE = System.getProperty("line.separator", "\r\n"); 43 44 /** 45 * Compare two strings for equality such that both can be null. 46 * 47 * @param string1 the first string 48 * @param string2 the second string 49 * @return true when both are null or both have the same string value 50 */ 51 public static boolean equals(String string1, String string2) { 52 if (string1 == null) { 53 return string2 == null; 54 } 55 return string1.equals(string2); 56 } 57 58 /** 59 * This method reads an InputStream <b>In its entirety</b>, and passes The 60 * text back as a string. If you are reading from a source that can block 61 * then be prepared for a long wait for this to return. 62 * 63 * @param in 64 * The Stream to read from. 65 * @return A string containing all the text from the Stream. 66 * @throws IOException when an I/O error occurred 67 */ 68 public static String read(Reader in) throws IOException { 69 StringBuilder retcode = new StringBuilder(); 70 // Quiet Android from complaining about using the default BufferReader buffer size. 71 // The actual buffer size is undocumented. So this is a good idea any way. 72 BufferedReader din = new BufferedReader(in, 8192); 73 74 while (true) { 75 String line = din.readLine(); 76 77 if (line == null) { 78 break; 79 } 80 81 retcode.append(line); 82 retcode.append(NEWLINE); 83 } 84 85 return retcode.toString(); 86 } 87 88 /** 89 * This function creates a readable title from a variable name type input. 90 * For example calling: StringUtil.createTitle("one_two") = "One Two" 91 * StringUtil.createTitle("oneTwo") = "One Two" 92 * 93 * @param variable the name of a variable 94 * @return the generated title 95 */ 96 public static String createTitle(String variable) { 97 StringBuilder retcode = new StringBuilder(); 98 boolean lastlower = false; 99 boolean lastspace = true; 100 101 for (int i = 0; i < variable.length(); i++) { 102 char c = variable.charAt(i); 103 104 if (lastlower && Character.isUpperCase(c) && !lastspace) { 105 retcode.append(' '); 106 } 107 108 lastlower = !Character.isUpperCase(c); 109 110 if (lastspace) { 111 c = Character.toUpperCase(c); 112 } 113 114 if (c == '_') { 115 c = ' '; 116 } 117 118 if (!lastspace || c != ' ') { 119 retcode.append(c); 120 } 121 122 lastspace = c == ' '; 123 } 124 125 return retcode.toString(); 126 } 127 128 /** 129 * For example getInitials("Java DataBase Connectivity") = "JDC" and 130 * getInitials("Church of England") = "CoE". 131 * 132 * @param sentence 133 * The phrase from which to get the initial letters. 134 * @return The initial letters in the given words. 135 */ 136 public static String getInitials(String sentence) { 137 String[] words = StringUtil.split(sentence); 138 139 StringBuilder retcode = new StringBuilder(); 140 for (int i = 0; i < words.length; i++) { 141 String word = words[i]; 142 143 char first = 0; 144 for (int j = 0; first == 0 && j < word.length(); j++) { 145 char c = word.charAt(j); 146 if (Character.isLetter(c)) { 147 first = c; 148 } 149 } 150 151 if (first != 0) { 152 retcode.append(first); 153 } 154 } 155 156 return retcode.toString(); 157 } 158 159 /** 160 * Splits the provided text into an array, using whitespace as the 161 * separator. Whitespace is defined by {@link Character#isWhitespace(char)}. 162 * 163 * <p> 164 * The separator is not included in the returned String array. Adjacent 165 * separators are treated as one separator. 166 * </p> 167 * 168 * <pre> 169 * StringUtil.split(null) = [] 170 * StringUtil.split("") = [] 171 * StringUtil.split("abc def") = ["abc", "def"] 172 * StringUtil.split("abc def") = ["abc", "def"] 173 * StringUtil.split(" abc ") = ["abc"] 174 * </pre> 175 * 176 * @param str 177 * the String to parse, may be null 178 * @return an array of parsed Strings, <code>null</code> if null String 179 * input 180 */ 181 public static String[] split(String str) { 182 if (str == null) { 183 return EMPTY_STRING_ARRAY.clone(); 184 } 185 186 int len = str.length(); 187 if (len == 0) { 188 return EMPTY_STRING_ARRAY.clone(); 189 } 190 191 char[] cstr = str.toCharArray(); 192 193 int count = 0; 194 int start = 0; 195 int i = 0; 196 while ((i = indexOfWhitespace(cstr, start)) != -1) { 197 // Don't count separator at beginning, 198 // after another or at the end 199 if (i > start) { 200 ++count; 201 } 202 start = i + 1; 203 } 204 205 // If it didn't end with a separator then add in the last part 206 if (start < len) { 207 ++count; 208 } 209 210 // Create the array 211 String[] list = new String[count]; 212 213 // If there were no separators 214 // then we have one big part 215 if (start == 0) { 216 list[0] = str; 217 return list; 218 } 219 220 start = 0; 221 i = 0; 222 int x = 0; 223 while ((i = indexOfWhitespace(cstr, start)) != -1) { 224 // Don't count separator at beginning, 225 // after another or at the end 226 if (i > start) { 227 list[x++] = str.substring(start, i); 228 } 229 start = i + 1; 230 } 231 // If it didn't end with a separator then add in the last part 232 if (start < len) { 233 list[x++] = str.substring(start); 234 } 235 236 return list; 237 } 238 239 /** 240 * Splits the provided text into an array, using whitespace as the 241 * separator. Whitespace is defined by {@link Character#isWhitespace(char)}. 242 * 243 * <p> 244 * The separator is not included in the returned String array. Adjacent 245 * separators are treated as one separator. 246 * </p> 247 * 248 * <pre> 249 * StringUtil.split(null) = [] 250 * StringUtil.split("") = [] 251 * StringUtil.split("abc def") = ["abc", "def"] 252 * StringUtil.split("abc def") = ["abc", "def"] 253 * StringUtil.split(" abc ") = ["abc"] 254 * </pre> 255 * 256 * @param str 257 * the String to parse, may be null 258 * @param max the maximum number of elements to return 259 * @return an array of parsed Strings, <code>null</code> if null String 260 * input 261 */ 262 public static String[] split(String str, int max) { 263 if (str == null) { 264 return EMPTY_STRING_ARRAY.clone(); 265 } 266 267 int len = str.length(); 268 if (len == 0) { 269 return EMPTY_STRING_ARRAY.clone(); 270 } 271 272 char[] cstr = str.toCharArray(); 273 274 int count = 0; 275 int start = 0; 276 int i = 0; 277 while ((i = indexOfWhitespace(cstr, start)) != -1) { 278 // Don't count separator at beginning, 279 // after another or at the end 280 if (i > start) { 281 ++count; 282 } 283 start = i + 1; 284 } 285 286 // If it didn't end with a separator then add in the last part 287 if (start < len) { 288 ++count; 289 } 290 291 // If there were no separators 292 // then we have one big part 293 if (start == 0) { 294 String[] list = new String[count]; 295 list[0] = str; 296 return list; 297 } 298 299 // Limit the result 300 if (max > 0 && count > max) { 301 count = max; 302 } 303 304 // Create the array 305 String[] list = new String[count]; 306 307 start = 0; 308 i = 0; 309 int x = 0; 310 while ((i = indexOfWhitespace(cstr, start)) != -1) { 311 // Don't count separator at beginning, 312 // after another or at the end 313 if (i > start && x < count) { 314 list[x++] = str.substring(start, i); 315 } 316 start = i + 1; 317 } 318 // If it didn't end with a separator then add in the last part 319 if (start < len && x < count) { 320 list[x++] = str.substring(start); 321 } 322 323 return list; 324 } 325 326 /** 327 * Splits the provided text into an array, separator specified. This is an 328 * alternative to using StringTokenizer. 329 * 330 * <p> 331 * The separator is not included in the returned String array. Adjacent 332 * separators are treated as one separator. 333 * </p> 334 * 335 * <p> 336 * A <code>null</code> input String returns <code>null</code>. 337 * </p> 338 * 339 * <pre> 340 * StringUtil.split(null, *) = [] 341 * StringUtil.split("", *) = [] 342 * StringUtil.split("a.b.c", '.') = ["a", "b", "c"] 343 * StringUtil.split("a..b.c", '.') = ["a", "b", "c"] 344 * StringUtil.split("a:b:c", '.') = ["a:b:c"] 345 * StringUtil.split("a b c", ' ') = ["a", "b", "c"] 346 * </pre> 347 * 348 * @param str 349 * the String to parse, may be null 350 * @param separatorChar 351 * the character used as the delimiter 352 * @return an array of parsed Strings 353 */ 354 public static String[] split(String str, char separatorChar) { 355 if (str == null) { 356 return EMPTY_STRING_ARRAY.clone(); 357 } 358 359 int len = str.length(); 360 if (len == 0) { 361 return EMPTY_STRING_ARRAY.clone(); 362 } 363 364 // Determine the size of the array 365 int count = 0; 366 int start = 0; 367 int i = 0; 368 while ((i = str.indexOf(separatorChar, start)) != -1) { 369 // Don't count separator at beginning, 370 // after another or at the end 371 if (i > start && i < len) { 372 ++count; 373 } 374 start = i + 1; 375 } 376 // If it didn't end with a separator then add in the last part 377 if (start < len) { 378 ++count; 379 } 380 381 // Create the array 382 String[] list = new String[count]; 383 384 // If there were no separators 385 // then we have one big part 386 if (count == 1) { 387 list[0] = str; 388 return list; 389 } 390 391 start = 0; 392 i = 0; 393 int x = 0; 394 while ((i = str.indexOf(separatorChar, start)) != -1) { 395 // Don't count separator at beginning, 396 // after another or at the end 397 if (i > start) { 398 list[x++] = str.substring(start, i); 399 } 400 start = i + 1; 401 } 402 // If it didn't end with a separator then add in the last part 403 if (start < len) { 404 list[x++] = str.substring(start, len); 405 } 406 407 return list; 408 } 409 410 /** 411 * <p> 412 * Splits the provided text into an array, separator specified. This is an 413 * alternative to using StringTokenizer. 414 * </p> 415 * 416 * <p> 417 * The separator is not included in the returned String array. Adjacent 418 * separators are treated as one separator. 419 * </p> 420 * 421 * <p> 422 * A <code>null</code> input String returns <code>null</code>. 423 * </p> 424 * 425 * <pre> 426 * StringUtil.split(null, *, 2) = [] 427 * StringUtil.split("", *, 2) = [] 428 * StringUtil.split("a.b.c", '.', 2) = ["a", "b"] 429 * StringUtil.split("a..b.c", '.', 2) = ["a", "b"] 430 * StringUtil.split("a:b:c", '.', 2) = ["a:b:c"] 431 * StringUtil.split("a b c", ' ', 2) = ["a", "b"] 432 * </pre> 433 * 434 * @param str 435 * the String to parse, may be null 436 * @param separatorChar 437 * the character used as the delimiter 438 * @param max 439 * the maximum number of elements to include in the array. 440 * A zero or negative value implies no limit 441 * @return an array of parsed Strings 442 */ 443 public static String[] split(String str, char separatorChar, int max) { 444 if (str == null) { 445 return EMPTY_STRING_ARRAY.clone(); 446 } 447 448 int len = str.length(); 449 if (len == 0) { 450 return EMPTY_STRING_ARRAY.clone(); 451 } 452 453 // Determine the size of the array 454 int count = 0; 455 int start = 0; 456 int i = 0; 457 while ((i = str.indexOf(separatorChar, start)) != -1) { 458 // Don't count separator at beginning, 459 // after another or at the end 460 if (i > start) { 461 ++count; 462 } 463 start = i + 1; 464 } 465 466 // If it didn't end with a separator then add in the last part 467 if (start < len) { 468 ++count; 469 } 470 471 // If there were no separators 472 // then we have one big part 473 if (count == 1) { 474 String[] list = new String[count]; 475 list[0] = str; 476 return list; 477 } 478 479 // Limit the result 480 if (max > 0 && count > max) { 481 count = max; 482 } 483 484 // Create the array 485 String[] list = new String[count]; 486 487 start = 0; 488 i = 0; 489 int x = 0; 490 while ((i = str.indexOf(separatorChar, start)) != -1) { 491 // Don't count separator at beginning, 492 // after another or at the end 493 if (i > start && x < count) { 494 list[x++] = str.substring(start, i); 495 } 496 start = i + 1; 497 } 498 // If it didn't end with a separator then add in the last part 499 if (start < len && x < count) { 500 list[x++] = str.substring(start); 501 } 502 503 return list; 504 } 505 506 /** 507 * <p> 508 * Splits the provided text into an array, separators specified. This is an 509 * alternative to using StringTokenizer. 510 * </p> 511 * 512 * <p> 513 * The separator is not included in the returned String array. Adjacent 514 * separators are treated as one separator. 515 * </p> 516 * 517 * <p> 518 * A <code>null</code> input String returns <code>null</code>. A 519 * <code>null</code> separatorChars splits on whitespace. 520 * </p> 521 * 522 * <pre> 523 * StringUtil.split(null, *) = [] 524 * StringUtil.split("", *) = [] 525 * StringUtil.split("abc def", null) = ["abc", "def"] 526 * StringUtil.split("abc def", " ") = ["abc", "def"] 527 * StringUtil.split("abc def", " ") = ["abc", "def"] 528 * StringUtil.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] 529 * </pre> 530 * 531 * @param str 532 * the String to parse, may be null 533 * @param separatorChars 534 * the characters used as the delimiters, <code>null</code> 535 * splits on whitespace 536 * @return an array of parsed Strings, <code>null</code> if null String 537 * input 538 */ 539 public static String[] split(String str, String separatorChars) { 540 return split(str, separatorChars, -1); 541 } 542 543 /** 544 * <p> 545 * Splits the provided text into an array, separators specified. This is an 546 * alternative to using StringTokenizer. 547 * </p> 548 * 549 * <p> 550 * The separator is not included in the returned String array. Adjacent 551 * separators are treated as one separator. 552 * </p> 553 * 554 * <p> 555 * A <code>null</code> input String returns <code>null</code>. A 556 * <code>null</code> separatorChars splits on whitespace. 557 * </p> 558 * 559 * <pre> 560 * StringUtil.split(null, *, *) = [] 561 * StringUtil.split("", *, *) = [] 562 * StringUtil.split("ab de fg", null, 0) = ["ab", "cd", "ef"] 563 * StringUtil.split("ab de fg", null, 0) = ["ab", "cd", "ef"] 564 * StringUtil.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 565 * StringUtil.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 566 * </pre> 567 * 568 * @param str 569 * the String to parse, may be null 570 * @param separatorStr 571 * the characters used as the delimiters, <code>null</code> 572 * splits on whitespace 573 * @param max 574 * the maximum number of elements to include in the array. A zero 575 * or negative value implies no limit 576 * @return an array of parsed Strings 577 */ 578 public static String[] split(String str, String separatorStr, int max) { 579 // Performance tuned for 2.0 (JDK1.4) 580 // Direct code is quicker than StringTokenizer. 581 // Also, StringTokenizer uses isSpace() not isWhitespace() 582 583 if (separatorStr == null) { 584 return split(str, max); 585 } 586 587 if (separatorStr.length() == 1) { 588 return split(str, separatorStr.charAt(0), max); 589 } 590 591 if (str == null) { 592 return EMPTY_STRING_ARRAY.clone(); 593 } 594 595 int len = str.length(); 596 if (len == 0) { 597 return EMPTY_STRING_ARRAY.clone(); 598 } 599 600 char[] cstr = str.toCharArray(); 601 char[] separatorChars = separatorStr.toCharArray(); 602 603 int count = 0; 604 int start = 0; 605 int i = 0; 606 while ((i = indexOfAny(cstr, separatorChars, start)) != -1) { 607 // Don't count separator at beginning, 608 // after another or at the end 609 if (i > start) { 610 ++count; 611 } 612 start = i + 1; 613 } 614 615 // If it didn't end with a separator then add in the last part 616 if (start < len) { 617 ++count; 618 } 619 620 // If there were no separators 621 // then we have one big part 622 if (count == 1) { 623 String[] list = new String[count]; 624 list[0] = str; 625 return list; 626 } 627 628 // Limit the result 629 if (max > 0 && count > max) { 630 count = max; 631 } 632 633 // Create the array 634 String[] list = new String[count]; 635 636 start = 0; 637 i = 0; 638 int x = 0; 639 while ((i = indexOfAny(cstr, separatorChars, start)) != -1) { 640 // Don't count separator at beginning, 641 // after another or at the end 642 if (i > start && x < count) { 643 list[x++] = str.substring(start, i); 644 } 645 start = i + 1; 646 } 647 // If it didn't end with a separator then add in the last part 648 if (start < len && x < count) { 649 list[x++] = str.substring(start); 650 } 651 652 return list; 653 } 654 655 /** 656 * <p> 657 * Splits the provided text into an array, separator specified. This is an 658 * alternative to using StringTokenizer. 659 * </p> 660 * 661 * <p> 662 * The separator is not included in the returned String array. Adjacent 663 * separators are treated individually. 664 * </p> 665 * 666 * <p> 667 * A <code>null</code> input String returns <code>null</code>. 668 * </p> 669 * 670 * <pre> 671 * StringUtil.splitAll(null, *) = [] 672 * StringUtil.splitAll("", *) = [] 673 * StringUtil.splitAll("a.b.c", '.') = ["a", "b", "c"] 674 * StringUtil.splitAll("a..b.c", '.') = ["a", "", "b", "c"] 675 * StringUtil.splitAll("a:b:c", '.') = ["a:b:c"] 676 * </pre> 677 * 678 * @param str 679 * the String to parse, may be null 680 * @param separatorChar 681 * the character used as the delimiter 682 * @return an array of parsed Strings 683 */ 684 public static String[] splitAll(String str, char separatorChar) { 685 if (str == null) { 686 return EMPTY_STRING_ARRAY.clone(); 687 } 688 689 int len = str.length(); 690 if (len == 0) { 691 return EMPTY_STRING_ARRAY.clone(); 692 } 693 694 // Determine the size of the array 695 int count = 1; 696 int start = 0; 697 int i = 0; 698 while ((i = str.indexOf(separatorChar, start)) != -1) { 699 ++count; 700 start = i + 1; 701 } 702 703 // Create the array 704 String[] list = new String[count]; 705 706 // If there were no separators 707 // then we have one big part 708 if (count == 1) { 709 list[0] = str; 710 return list; 711 } 712 713 start = 0; 714 i = 0; 715 for (int x = 0; x < count; x++) { 716 i = str.indexOf(separatorChar, start); 717 if (i != -1) { 718 list[x] = str.substring(start, i); 719 } else { 720 list[x] = str.substring(start); 721 } 722 start = i + 1; 723 } 724 725 return list; 726 } 727 728 /** 729 * <p> 730 * Splits the provided text into an array, separator specified. This is an 731 * alternative to using StringTokenizer. 732 * </p> 733 * 734 * <p> 735 * The separator is not included in the returned String array. Adjacent 736 * separators are treated individually. 737 * </p> 738 * 739 * <p> 740 * A <code>null</code> input String returns <code>null</code>. 741 * </p> 742 * 743 * <pre> 744 * StringUtil.splitAll(null, *, 2) = [] 745 * StringUtil.splitAll("", *, 2) = [] 746 * StringUtil.splitAll("a.b.c", '.', 2) = ["a", "b"] 747 * StringUtil.splitAll("a..b.c", '.', 2) = ["a", ""] 748 * StringUtil.splitAll("a:b:c", '.', 2) = ["a:b:c"] 749 * StringUtil.splitAll("a b c", ' ', 2) = ["a", "b"] 750 * </pre> 751 * 752 * @param str 753 * the String to parse, may be null 754 * @param separatorChar 755 * the character used as the delimiter 756 * @param max 757 * the maximum number of elements to include in the array. 758 * A zero or negative value implies no limit 759 * @return an array of parsed Strings 760 */ 761 public static String[] splitAll(String str, char separatorChar, int max) { 762 if (str == null) { 763 return EMPTY_STRING_ARRAY.clone(); 764 } 765 766 int len = str.length(); 767 if (len == 0) { 768 return EMPTY_STRING_ARRAY.clone(); 769 } 770 771 // Determine the size of the array 772 int count = 1; 773 int start = 0; 774 int i = 0; 775 while ((i = str.indexOf(separatorChar, start)) != -1) { 776 ++count; 777 start = i + 1; 778 } 779 780 // If there were no separators 781 // then we have one big part 782 if (count == 1) { 783 String[] list = new String[count]; 784 list[0] = str; 785 return list; 786 } 787 788 // Limit the result 789 if (max > 0 && count > max) { 790 count = max; 791 } 792 793 // Create the array 794 String[] list = new String[count]; 795 796 start = 0; 797 i = 0; 798 for (int x = 0; x < count; x++) { 799 i = str.indexOf(separatorChar, start); 800 if (i != -1) { 801 list[x] = str.substring(start, i); 802 } else { 803 list[x] = str.substring(start, len); 804 } 805 start = i + 1; 806 } 807 808 return list; 809 } 810 811 /** 812 * <p> 813 * Joins the elements of the provided array into a single String containing 814 * the provided list of elements. 815 * </p> 816 * 817 * <p> 818 * No delimiter is added before or after the list. A <code>null</code> 819 * separator is the same as an empty String (""). Null objects or empty 820 * strings within the array are represented by empty strings. 821 * </p> 822 * 823 * <pre> 824 * StringUtil.join(null, *) = null 825 * StringUtil.join([], *) = "" 826 * StringUtil.join([null], *) = "" 827 * StringUtil.join(["a", "b", "c"], "--") = "a--b--c" 828 * StringUtil.join(["a", "b", "c"], null) = "abc" 829 * StringUtil.join(["a", "b", "c"], "") = "abc" 830 * StringUtil.join([null, "", "a"], ',') = ",,a" 831 * </pre> 832 * 833 * @param array 834 * the array of values to join together, may be null 835 * @param aSeparator 836 * the separator character to use, null treated as "" 837 * @return the joined String, <code>null</code> if null array input 838 */ 839 public static String join(Object[] array, String aSeparator) { 840 String separator = aSeparator; 841 if (array == null) { 842 return null; 843 } 844 if (separator == null) { 845 separator = ""; 846 } 847 int arraySize = array.length; 848 849 // ArraySize == 0: Len = 0 850 // ArraySize > 0: Len = NofStrings *(len(firstString) + len(separator)) 851 // (Assuming that all Strings are roughly equally long) 852 int bufSize = arraySize == 0 ? 0 : arraySize * ((array[0] == null ? 16 : array[0].toString().length()) + separator.length()); 853 854 StringBuilder buf = new StringBuilder(bufSize); 855 856 for (int i = 0; i < arraySize; i++) { 857 if (i > 0) { 858 buf.append(separator); 859 } 860 if (array[i] != null) { 861 buf.append(array[i]); 862 } 863 } 864 return buf.toString(); 865 } 866 867 /** 868 * Find the first occurrence of a separator in the character buffer beginning 869 * at the given offset. 870 * 871 * @param str 872 * the String to parse, may be null 873 * @param separatorChars 874 * the characters used as the delimiters, <code>null</code> 875 * splits on whitespace 876 * @param offset 877 * the index of the first character to consider 878 * @return the index of a separator char in the string or -1 879 */ 880 public static int indexOfAny(char[] str, char[] separatorChars, int offset) { 881 int strlen = str.length; 882 int seplen = separatorChars.length; 883 for (int i = offset; i < strlen; i++) { 884 char ch = str[i]; 885 for (int j = 0; j < seplen; j++) { 886 if (separatorChars[j] == ch) { 887 return i; 888 } 889 } 890 } 891 return -1; 892 } 893 894 /** 895 * Find the first occurrence of a whitespace in the character buffer beginning 896 * at the given offset. 897 * Whitespace is defined by {@link Character#isWhitespace(char)}. 898 * 899 * @param str 900 * the String to parse, may be null 901 * @param offset 902 * the index of the first character to consider 903 * @return the index of a separator char in the string or -1 904 */ 905 public static int indexOfWhitespace(char[] str, int offset) { 906 int strlen = str.length; 907 for (int i = offset; i < strlen; i++) { 908 if (Character.isWhitespace(str[i])) { 909 return i; 910 } 911 } 912 return -1; 913 } 914 915 /** 916 * An empty immutable <code>String</code> array. 917 */ 918 public static final String[] EMPTY_STRING_ARRAY = new String[0]; 919 920 } 921