001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3; 018 019import java.io.UnsupportedEncodingException; 020import java.nio.charset.Charset; 021import java.text.Normalizer; 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.Iterator; 025import java.util.List; 026import java.util.Locale; 027import java.util.regex.Pattern; 028 029/** 030 * <p>Operations on {@link java.lang.String} that are 031 * {@code null} safe.</p> 032 * 033 * <ul> 034 * <li><b>IsEmpty/IsBlank</b> 035 * - checks if a String contains text</li> 036 * <li><b>Trim/Strip</b> 037 * - removes leading and trailing whitespace</li> 038 * <li><b>Equals</b> 039 * - compares two strings null-safe</li> 040 * <li><b>startsWith</b> 041 * - check if a String starts with a prefix null-safe</li> 042 * <li><b>endsWith</b> 043 * - check if a String ends with a suffix null-safe</li> 044 * <li><b>IndexOf/LastIndexOf/Contains</b> 045 * - null-safe index-of checks 046 * <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b> 047 * - index-of any of a set of Strings</li> 048 * <li><b>ContainsOnly/ContainsNone/ContainsAny</b> 049 * - does String contains only/none/any of these characters</li> 050 * <li><b>Substring/Left/Right/Mid</b> 051 * - null-safe substring extractions</li> 052 * <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b> 053 * - substring extraction relative to other strings</li> 054 * <li><b>Split/Join</b> 055 * - splits a String into an array of substrings and vice versa</li> 056 * <li><b>Remove/Delete</b> 057 * - removes part of a String</li> 058 * <li><b>Replace/Overlay</b> 059 * - Searches a String and replaces one String with another</li> 060 * <li><b>Chomp/Chop</b> 061 * - removes the last part of a String</li> 062 * <li><b>AppendIfMissing</b> 063 * - appends a suffix to the end of the String if not present</li> 064 * <li><b>PrependIfMissing</b> 065 * - prepends a prefix to the start of the String if not present</li> 066 * <li><b>LeftPad/RightPad/Center/Repeat</b> 067 * - pads a String</li> 068 * <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b> 069 * - changes the case of a String</li> 070 * <li><b>CountMatches</b> 071 * - counts the number of occurrences of one String in another</li> 072 * <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b> 073 * - checks the characters in a String</li> 074 * <li><b>DefaultString</b> 075 * - protects against a null input String</li> 076 * <li><b>Reverse/ReverseDelimited</b> 077 * - reverses a String</li> 078 * <li><b>Abbreviate</b> 079 * - abbreviates a string using ellipsis</li> 080 * <li><b>Difference</b> 081 * - compares Strings and reports on their differences</li> 082 * <li><b>LevenshteinDistance</b> 083 * - the number of changes needed to change one String into another</li> 084 * </ul> 085 * 086 * <p>The {@code StringUtils} class defines certain words related to 087 * String handling.</p> 088 * 089 * <ul> 090 * <li>null - {@code null}</li> 091 * <li>empty - a zero-length string ({@code ""})</li> 092 * <li>space - the space character ({@code ' '}, char 32)</li> 093 * <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li> 094 * <li>trim - the characters <= 32 as in {@link String#trim()}</li> 095 * </ul> 096 * 097 * <p>{@code StringUtils} handles {@code null} input Strings quietly. 098 * That is to say that a {@code null} input will return {@code null}. 099 * Where a {@code boolean} or {@code int} is being returned 100 * details vary by method.</p> 101 * 102 * <p>A side effect of the {@code null} handling is that a 103 * {@code NullPointerException} should be considered a bug in 104 * {@code StringUtils}.</p> 105 * 106 * <p>Methods in this class give sample code to explain their operation. 107 * The symbol {@code *} is used to indicate any input including {@code null}.</p> 108 * 109 * <p>#ThreadSafe#</p> 110 * @see java.lang.String 111 * @since 1.0 112 * @version $Id: StringUtils.java 1552671 2013-12-20 13:51:14Z britter $ 113 */ 114//@Immutable 115public class StringUtils { 116 // Performance testing notes (JDK 1.4, Jul03, scolebourne) 117 // Whitespace: 118 // Character.isWhitespace() is faster than WHITESPACE.indexOf() 119 // where WHITESPACE is a string of all whitespace characters 120 // 121 // Character access: 122 // String.charAt(n) versus toCharArray(), then array[n] 123 // String.charAt(n) is about 15% worse for a 10K string 124 // They are about equal for a length 50 string 125 // String.charAt(n) is about 4 times better for a length 3 string 126 // String.charAt(n) is best bet overall 127 // 128 // Append: 129 // String.concat about twice as fast as StringBuffer.append 130 // (not sure who tested this) 131 132 /** 133 * A String for a space character. 134 * 135 * @since 3.2 136 */ 137 public static final String SPACE = " "; 138 139 /** 140 * The empty String {@code ""}. 141 * @since 2.0 142 */ 143 public static final String EMPTY = ""; 144 145 /** 146 * A String for linefeed LF ("\n"). 147 * 148 * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 149 * for Character and String Literals</a> 150 * @since 3.2 151 */ 152 public static final String LF = "\n"; 153 154 /** 155 * A String for carriage return CR ("\r"). 156 * 157 * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 158 * for Character and String Literals</a> 159 * @since 3.2 160 */ 161 public static final String CR = "\r"; 162 163 /** 164 * Represents a failed index search. 165 * @since 2.1 166 */ 167 public static final int INDEX_NOT_FOUND = -1; 168 169 /** 170 * <p>The maximum size to which the padding constant(s) can expand.</p> 171 */ 172 private static final int PAD_LIMIT = 8192; 173 174 /** 175 * A regex pattern for recognizing blocks of whitespace characters. 176 * The apparent convolutedness of the pattern serves the purpose of 177 * ignoring "blocks" consisting of only a single space: the pattern 178 * is used only to normalize whitespace, condensing "blocks" down to a 179 * single space, thus matching the same would likely cause a great 180 * many noop replacements. 181 */ 182 private static final Pattern WHITESPACE_PATTERN = Pattern.compile("(?: |\\u00A0|\\s|[\\s&&[^ ]])\\s*"); 183 184 /** 185 * <p>{@code StringUtils} instances should NOT be constructed in 186 * standard programming. Instead, the class should be used as 187 * {@code StringUtils.trim(" foo ");}.</p> 188 * 189 * <p>This constructor is public to permit tools that require a JavaBean 190 * instance to operate.</p> 191 */ 192 public StringUtils() { 193 super(); 194 } 195 196 // Empty checks 197 //----------------------------------------------------------------------- 198 /** 199 * <p>Checks if a CharSequence is empty ("") or null.</p> 200 * 201 * <pre> 202 * StringUtils.isEmpty(null) = true 203 * StringUtils.isEmpty("") = true 204 * StringUtils.isEmpty(" ") = false 205 * StringUtils.isEmpty("bob") = false 206 * StringUtils.isEmpty(" bob ") = false 207 * </pre> 208 * 209 * <p>NOTE: This method changed in Lang version 2.0. 210 * It no longer trims the CharSequence. 211 * That functionality is available in isBlank().</p> 212 * 213 * @param cs the CharSequence to check, may be null 214 * @return {@code true} if the CharSequence is empty or null 215 * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) 216 */ 217 public static boolean isEmpty(final CharSequence cs) { 218 return cs == null || cs.length() == 0; 219 } 220 221 /** 222 * <p>Checks if a CharSequence is not empty ("") and not null.</p> 223 * 224 * <pre> 225 * StringUtils.isNotEmpty(null) = false 226 * StringUtils.isNotEmpty("") = false 227 * StringUtils.isNotEmpty(" ") = true 228 * StringUtils.isNotEmpty("bob") = true 229 * StringUtils.isNotEmpty(" bob ") = true 230 * </pre> 231 * 232 * @param cs the CharSequence to check, may be null 233 * @return {@code true} if the CharSequence is not empty and not null 234 * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) 235 */ 236 public static boolean isNotEmpty(final CharSequence cs) { 237 return !StringUtils.isEmpty(cs); 238 } 239 240 /** 241 * <p>Checks if any one of the CharSequences are empty ("") or null.</p> 242 * 243 * <pre> 244 * StringUtils.isAnyEmpty(null) = true 245 * StringUtils.isAnyEmpty(null, "foo") = true 246 * StringUtils.isAnyEmpty("", "bar") = true 247 * StringUtils.isAnyEmpty("bob", "") = true 248 * StringUtils.isAnyEmpty(" bob ", null) = true 249 * StringUtils.isAnyEmpty(" ", "bar") = false 250 * StringUtils.isAnyEmpty("foo", "bar") = false 251 * </pre> 252 * 253 * @param css the CharSequences to check, may be null or empty 254 * @return {@code true} if any of the CharSequences are empty or null 255 * @since 3.2 256 */ 257 public static boolean isAnyEmpty(CharSequence... css) { 258 if (ArrayUtils.isEmpty(css)) { 259 return true; 260 } 261 for (CharSequence cs : css){ 262 if (isEmpty(cs)) { 263 return true; 264 } 265 } 266 return false; 267 } 268 269 /** 270 * <p>Checks if none of the CharSequences are empty ("") or null.</p> 271 * 272 * <pre> 273 * StringUtils.isNoneEmpty(null) = false 274 * StringUtils.isNoneEmpty(null, "foo") = false 275 * StringUtils.isNoneEmpty("", "bar") = false 276 * StringUtils.isNoneEmpty("bob", "") = false 277 * StringUtils.isNoneEmpty(" bob ", null) = false 278 * StringUtils.isNoneEmpty(" ", "bar") = true 279 * StringUtils.isNoneEmpty("foo", "bar") = true 280 * </pre> 281 * 282 * @param css the CharSequences to check, may be null or empty 283 * @return {@code true} if none of the CharSequences are empty or null 284 * @since 3.2 285 */ 286 public static boolean isNoneEmpty(CharSequence... css) { 287 return !isAnyEmpty(css); 288 } 289 /** 290 * <p>Checks if a CharSequence is whitespace, empty ("") or null.</p> 291 * 292 * <pre> 293 * StringUtils.isBlank(null) = true 294 * StringUtils.isBlank("") = true 295 * StringUtils.isBlank(" ") = true 296 * StringUtils.isBlank("bob") = false 297 * StringUtils.isBlank(" bob ") = false 298 * </pre> 299 * 300 * @param cs the CharSequence to check, may be null 301 * @return {@code true} if the CharSequence is null, empty or whitespace 302 * @since 2.0 303 * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) 304 */ 305 public static boolean isBlank(final CharSequence cs) { 306 int strLen; 307 if (cs == null || (strLen = cs.length()) == 0) { 308 return true; 309 } 310 for (int i = 0; i < strLen; i++) { 311 if (Character.isWhitespace(cs.charAt(i)) == false) { 312 return false; 313 } 314 } 315 return true; 316 } 317 318 /** 319 * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p> 320 * 321 * <pre> 322 * StringUtils.isNotBlank(null) = false 323 * StringUtils.isNotBlank("") = false 324 * StringUtils.isNotBlank(" ") = false 325 * StringUtils.isNotBlank("bob") = true 326 * StringUtils.isNotBlank(" bob ") = true 327 * </pre> 328 * 329 * @param cs the CharSequence to check, may be null 330 * @return {@code true} if the CharSequence is 331 * not empty and not null and not whitespace 332 * @since 2.0 333 * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) 334 */ 335 public static boolean isNotBlank(final CharSequence cs) { 336 return !StringUtils.isBlank(cs); 337 } 338 339 /** 340 * <p>Checks if any one of the CharSequences are blank ("") or null and not whitespace only..</p> 341 * 342 * <pre> 343 * StringUtils.isAnyBlank(null) = true 344 * StringUtils.isAnyBlank(null, "foo") = true 345 * StringUtils.isAnyBlank(null, null) = true 346 * StringUtils.isAnyBlank("", "bar") = true 347 * StringUtils.isAnyBlank("bob", "") = true 348 * StringUtils.isAnyBlank(" bob ", null) = true 349 * StringUtils.isAnyBlank(" ", "bar") = true 350 * StringUtils.isAnyBlank("foo", "bar") = false 351 * </pre> 352 * 353 * @param css the CharSequences to check, may be null or empty 354 * @return {@code true} if any of the CharSequences are blank or null or whitespace only 355 * @since 3.2 356 */ 357 public static boolean isAnyBlank(CharSequence... css) { 358 if (ArrayUtils.isEmpty(css)) { 359 return true; 360 } 361 for (CharSequence cs : css){ 362 if (isBlank(cs)) { 363 return true; 364 } 365 } 366 return false; 367 } 368 369 /** 370 * <p>Checks if none of the CharSequences are blank ("") or null and whitespace only..</p> 371 * 372 * <pre> 373 * StringUtils.isNoneBlank(null) = false 374 * StringUtils.isNoneBlank(null, "foo") = false 375 * StringUtils.isNoneBlank(null, null) = false 376 * StringUtils.isNoneBlank("", "bar") = false 377 * StringUtils.isNoneBlank("bob", "") = false 378 * StringUtils.isNoneBlank(" bob ", null) = false 379 * StringUtils.isNoneBlank(" ", "bar") = false 380 * StringUtils.isNoneBlank("foo", "bar") = true 381 * </pre> 382 * 383 * @param css the CharSequences to check, may be null or empty 384 * @return {@code true} if none of the CharSequences are blank or null or whitespace only 385 * @since 3.2 386 */ 387 public static boolean isNoneBlank(CharSequence... css) { 388 return !isAnyBlank(css); 389 } 390 391 // Trim 392 //----------------------------------------------------------------------- 393 /** 394 * <p>Removes control characters (char <= 32) from both 395 * ends of this String, handling {@code null} by returning 396 * {@code null}.</p> 397 * 398 * <p>The String is trimmed using {@link String#trim()}. 399 * Trim removes start and end characters <= 32. 400 * To strip whitespace use {@link #strip(String)}.</p> 401 * 402 * <p>To trim your choice of characters, use the 403 * {@link #strip(String, String)} methods.</p> 404 * 405 * <pre> 406 * StringUtils.trim(null) = null 407 * StringUtils.trim("") = "" 408 * StringUtils.trim(" ") = "" 409 * StringUtils.trim("abc") = "abc" 410 * StringUtils.trim(" abc ") = "abc" 411 * </pre> 412 * 413 * @param str the String to be trimmed, may be null 414 * @return the trimmed string, {@code null} if null String input 415 */ 416 public static String trim(final String str) { 417 return str == null ? null : str.trim(); 418 } 419 420 /** 421 * <p>Removes control characters (char <= 32) from both 422 * ends of this String returning {@code null} if the String is 423 * empty ("") after the trim or if it is {@code null}. 424 * 425 * <p>The String is trimmed using {@link String#trim()}. 426 * Trim removes start and end characters <= 32. 427 * To strip whitespace use {@link #stripToNull(String)}.</p> 428 * 429 * <pre> 430 * StringUtils.trimToNull(null) = null 431 * StringUtils.trimToNull("") = null 432 * StringUtils.trimToNull(" ") = null 433 * StringUtils.trimToNull("abc") = "abc" 434 * StringUtils.trimToNull(" abc ") = "abc" 435 * </pre> 436 * 437 * @param str the String to be trimmed, may be null 438 * @return the trimmed String, 439 * {@code null} if only chars <= 32, empty or null String input 440 * @since 2.0 441 */ 442 public static String trimToNull(final String str) { 443 final String ts = trim(str); 444 return isEmpty(ts) ? null : ts; 445 } 446 447 /** 448 * <p>Removes control characters (char <= 32) from both 449 * ends of this String returning an empty String ("") if the String 450 * is empty ("") after the trim or if it is {@code null}. 451 * 452 * <p>The String is trimmed using {@link String#trim()}. 453 * Trim removes start and end characters <= 32. 454 * To strip whitespace use {@link #stripToEmpty(String)}.</p> 455 * 456 * <pre> 457 * StringUtils.trimToEmpty(null) = "" 458 * StringUtils.trimToEmpty("") = "" 459 * StringUtils.trimToEmpty(" ") = "" 460 * StringUtils.trimToEmpty("abc") = "abc" 461 * StringUtils.trimToEmpty(" abc ") = "abc" 462 * </pre> 463 * 464 * @param str the String to be trimmed, may be null 465 * @return the trimmed String, or an empty String if {@code null} input 466 * @since 2.0 467 */ 468 public static String trimToEmpty(final String str) { 469 return str == null ? EMPTY : str.trim(); 470 } 471 472 // Stripping 473 //----------------------------------------------------------------------- 474 /** 475 * <p>Strips whitespace from the start and end of a String.</p> 476 * 477 * <p>This is similar to {@link #trim(String)} but removes whitespace. 478 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 479 * 480 * <p>A {@code null} input String returns {@code null}.</p> 481 * 482 * <pre> 483 * StringUtils.strip(null) = null 484 * StringUtils.strip("") = "" 485 * StringUtils.strip(" ") = "" 486 * StringUtils.strip("abc") = "abc" 487 * StringUtils.strip(" abc") = "abc" 488 * StringUtils.strip("abc ") = "abc" 489 * StringUtils.strip(" abc ") = "abc" 490 * StringUtils.strip(" ab c ") = "ab c" 491 * </pre> 492 * 493 * @param str the String to remove whitespace from, may be null 494 * @return the stripped String, {@code null} if null String input 495 */ 496 public static String strip(final String str) { 497 return strip(str, null); 498 } 499 500 /** 501 * <p>Strips whitespace from the start and end of a String returning 502 * {@code null} if the String is empty ("") after the strip.</p> 503 * 504 * <p>This is similar to {@link #trimToNull(String)} but removes whitespace. 505 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 506 * 507 * <pre> 508 * StringUtils.stripToNull(null) = null 509 * StringUtils.stripToNull("") = null 510 * StringUtils.stripToNull(" ") = null 511 * StringUtils.stripToNull("abc") = "abc" 512 * StringUtils.stripToNull(" abc") = "abc" 513 * StringUtils.stripToNull("abc ") = "abc" 514 * StringUtils.stripToNull(" abc ") = "abc" 515 * StringUtils.stripToNull(" ab c ") = "ab c" 516 * </pre> 517 * 518 * @param str the String to be stripped, may be null 519 * @return the stripped String, 520 * {@code null} if whitespace, empty or null String input 521 * @since 2.0 522 */ 523 public static String stripToNull(String str) { 524 if (str == null) { 525 return null; 526 } 527 str = strip(str, null); 528 return str.isEmpty() ? null : str; 529 } 530 531 /** 532 * <p>Strips whitespace from the start and end of a String returning 533 * an empty String if {@code null} input.</p> 534 * 535 * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace. 536 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 537 * 538 * <pre> 539 * StringUtils.stripToEmpty(null) = "" 540 * StringUtils.stripToEmpty("") = "" 541 * StringUtils.stripToEmpty(" ") = "" 542 * StringUtils.stripToEmpty("abc") = "abc" 543 * StringUtils.stripToEmpty(" abc") = "abc" 544 * StringUtils.stripToEmpty("abc ") = "abc" 545 * StringUtils.stripToEmpty(" abc ") = "abc" 546 * StringUtils.stripToEmpty(" ab c ") = "ab c" 547 * </pre> 548 * 549 * @param str the String to be stripped, may be null 550 * @return the trimmed String, or an empty String if {@code null} input 551 * @since 2.0 552 */ 553 public static String stripToEmpty(final String str) { 554 return str == null ? EMPTY : strip(str, null); 555 } 556 557 /** 558 * <p>Strips any of a set of characters from the start and end of a String. 559 * This is similar to {@link String#trim()} but allows the characters 560 * to be stripped to be controlled.</p> 561 * 562 * <p>A {@code null} input String returns {@code null}. 563 * An empty string ("") input returns the empty string.</p> 564 * 565 * <p>If the stripChars String is {@code null}, whitespace is 566 * stripped as defined by {@link Character#isWhitespace(char)}. 567 * Alternatively use {@link #strip(String)}.</p> 568 * 569 * <pre> 570 * StringUtils.strip(null, *) = null 571 * StringUtils.strip("", *) = "" 572 * StringUtils.strip("abc", null) = "abc" 573 * StringUtils.strip(" abc", null) = "abc" 574 * StringUtils.strip("abc ", null) = "abc" 575 * StringUtils.strip(" abc ", null) = "abc" 576 * StringUtils.strip(" abcyx", "xyz") = " abc" 577 * </pre> 578 * 579 * @param str the String to remove characters from, may be null 580 * @param stripChars the characters to remove, null treated as whitespace 581 * @return the stripped String, {@code null} if null String input 582 */ 583 public static String strip(String str, final String stripChars) { 584 if (isEmpty(str)) { 585 return str; 586 } 587 str = stripStart(str, stripChars); 588 return stripEnd(str, stripChars); 589 } 590 591 /** 592 * <p>Strips any of a set of characters from the start of a String.</p> 593 * 594 * <p>A {@code null} input String returns {@code null}. 595 * An empty string ("") input returns the empty string.</p> 596 * 597 * <p>If the stripChars String is {@code null}, whitespace is 598 * stripped as defined by {@link Character#isWhitespace(char)}.</p> 599 * 600 * <pre> 601 * StringUtils.stripStart(null, *) = null 602 * StringUtils.stripStart("", *) = "" 603 * StringUtils.stripStart("abc", "") = "abc" 604 * StringUtils.stripStart("abc", null) = "abc" 605 * StringUtils.stripStart(" abc", null) = "abc" 606 * StringUtils.stripStart("abc ", null) = "abc " 607 * StringUtils.stripStart(" abc ", null) = "abc " 608 * StringUtils.stripStart("yxabc ", "xyz") = "abc " 609 * </pre> 610 * 611 * @param str the String to remove characters from, may be null 612 * @param stripChars the characters to remove, null treated as whitespace 613 * @return the stripped String, {@code null} if null String input 614 */ 615 public static String stripStart(final String str, final String stripChars) { 616 int strLen; 617 if (str == null || (strLen = str.length()) == 0) { 618 return str; 619 } 620 int start = 0; 621 if (stripChars == null) { 622 while (start != strLen && Character.isWhitespace(str.charAt(start))) { 623 start++; 624 } 625 } else if (stripChars.isEmpty()) { 626 return str; 627 } else { 628 while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) { 629 start++; 630 } 631 } 632 return str.substring(start); 633 } 634 635 /** 636 * <p>Strips any of a set of characters from the end of a String.</p> 637 * 638 * <p>A {@code null} input String returns {@code null}. 639 * An empty string ("") input returns the empty string.</p> 640 * 641 * <p>If the stripChars String is {@code null}, whitespace is 642 * stripped as defined by {@link Character#isWhitespace(char)}.</p> 643 * 644 * <pre> 645 * StringUtils.stripEnd(null, *) = null 646 * StringUtils.stripEnd("", *) = "" 647 * StringUtils.stripEnd("abc", "") = "abc" 648 * StringUtils.stripEnd("abc", null) = "abc" 649 * StringUtils.stripEnd(" abc", null) = " abc" 650 * StringUtils.stripEnd("abc ", null) = "abc" 651 * StringUtils.stripEnd(" abc ", null) = " abc" 652 * StringUtils.stripEnd(" abcyx", "xyz") = " abc" 653 * StringUtils.stripEnd("120.00", ".0") = "12" 654 * </pre> 655 * 656 * @param str the String to remove characters from, may be null 657 * @param stripChars the set of characters to remove, null treated as whitespace 658 * @return the stripped String, {@code null} if null String input 659 */ 660 public static String stripEnd(final String str, final String stripChars) { 661 int end; 662 if (str == null || (end = str.length()) == 0) { 663 return str; 664 } 665 666 if (stripChars == null) { 667 while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { 668 end--; 669 } 670 } else if (stripChars.isEmpty()) { 671 return str; 672 } else { 673 while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) { 674 end--; 675 } 676 } 677 return str.substring(0, end); 678 } 679 680 // StripAll 681 //----------------------------------------------------------------------- 682 /** 683 * <p>Strips whitespace from the start and end of every String in an array. 684 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 685 * 686 * <p>A new array is returned each time, except for length zero. 687 * A {@code null} array will return {@code null}. 688 * An empty array will return itself. 689 * A {@code null} array entry will be ignored.</p> 690 * 691 * <pre> 692 * StringUtils.stripAll(null) = null 693 * StringUtils.stripAll([]) = [] 694 * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"] 695 * StringUtils.stripAll(["abc ", null]) = ["abc", null] 696 * </pre> 697 * 698 * @param strs the array to remove whitespace from, may be null 699 * @return the stripped Strings, {@code null} if null array input 700 */ 701 public static String[] stripAll(final String... strs) { 702 return stripAll(strs, null); 703 } 704 705 /** 706 * <p>Strips any of a set of characters from the start and end of every 707 * String in an array.</p> 708 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 709 * 710 * <p>A new array is returned each time, except for length zero. 711 * A {@code null} array will return {@code null}. 712 * An empty array will return itself. 713 * A {@code null} array entry will be ignored. 714 * A {@code null} stripChars will strip whitespace as defined by 715 * {@link Character#isWhitespace(char)}.</p> 716 * 717 * <pre> 718 * StringUtils.stripAll(null, *) = null 719 * StringUtils.stripAll([], *) = [] 720 * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"] 721 * StringUtils.stripAll(["abc ", null], null) = ["abc", null] 722 * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null] 723 * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null] 724 * </pre> 725 * 726 * @param strs the array to remove characters from, may be null 727 * @param stripChars the characters to remove, null treated as whitespace 728 * @return the stripped Strings, {@code null} if null array input 729 */ 730 public static String[] stripAll(final String[] strs, final String stripChars) { 731 int strsLen; 732 if (strs == null || (strsLen = strs.length) == 0) { 733 return strs; 734 } 735 final String[] newArr = new String[strsLen]; 736 for (int i = 0; i < strsLen; i++) { 737 newArr[i] = strip(strs[i], stripChars); 738 } 739 return newArr; 740 } 741 742 /** 743 * <p>Removes diacritics (~= accents) from a string. The case will not be altered.</p> 744 * <p>For instance, 'à' will be replaced by 'a'.</p> 745 * <p>Note that ligatures will be left as is.</p> 746 * 747 * <pre> 748 * StringUtils.stripAccents(null) = null 749 * StringUtils.stripAccents("") = "" 750 * StringUtils.stripAccents("control") = "control" 751 * StringUtils.stripAccents("éclair") = "eclair" 752 * </pre> 753 * 754 * @param input String to be stripped 755 * @return input text with diacritics removed 756 * 757 * @since 3.0 758 */ 759 // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907). 760 public static String stripAccents(final String input) { 761 if(input == null) { 762 return null; 763 } 764 final Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");//$NON-NLS-1$ 765 final String decomposed = Normalizer.normalize(input, Normalizer.Form.NFD); 766 // Note that this doesn't correctly remove ligatures... 767 return pattern.matcher(decomposed).replaceAll("");//$NON-NLS-1$ 768 } 769 770 // Equals 771 //----------------------------------------------------------------------- 772 /** 773 * <p>Compares two CharSequences, returning {@code true} if they represent 774 * equal sequences of characters.</p> 775 * 776 * <p>{@code null}s are handled without exceptions. Two {@code null} 777 * references are considered to be equal. The comparison is case sensitive.</p> 778 * 779 * <pre> 780 * StringUtils.equals(null, null) = true 781 * StringUtils.equals(null, "abc") = false 782 * StringUtils.equals("abc", null) = false 783 * StringUtils.equals("abc", "abc") = true 784 * StringUtils.equals("abc", "ABC") = false 785 * </pre> 786 * 787 * @see Object#equals(Object) 788 * @param cs1 the first CharSequence, may be {@code null} 789 * @param cs2 the second CharSequence, may be {@code null} 790 * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null} 791 * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence) 792 */ 793 public static boolean equals(final CharSequence cs1, final CharSequence cs2) { 794 if (cs1 == cs2) { 795 return true; 796 } 797 if (cs1 == null || cs2 == null) { 798 return false; 799 } 800 if (cs1 instanceof String && cs2 instanceof String) { 801 return cs1.equals(cs2); 802 } 803 return CharSequenceUtils.regionMatches(cs1, false, 0, cs2, 0, Math.max(cs1.length(), cs2.length())); 804 } 805 806 /** 807 * <p>Compares two CharSequences, returning {@code true} if they represent 808 * equal sequences of characters, ignoring case.</p> 809 * 810 * <p>{@code null}s are handled without exceptions. Two {@code null} 811 * references are considered equal. Comparison is case insensitive.</p> 812 * 813 * <pre> 814 * StringUtils.equalsIgnoreCase(null, null) = true 815 * StringUtils.equalsIgnoreCase(null, "abc") = false 816 * StringUtils.equalsIgnoreCase("abc", null) = false 817 * StringUtils.equalsIgnoreCase("abc", "abc") = true 818 * StringUtils.equalsIgnoreCase("abc", "ABC") = true 819 * </pre> 820 * 821 * @param str1 the first CharSequence, may be null 822 * @param str2 the second CharSequence, may be null 823 * @return {@code true} if the CharSequence are equal, case insensitive, or 824 * both {@code null} 825 * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence) 826 */ 827 public static boolean equalsIgnoreCase(final CharSequence str1, final CharSequence str2) { 828 if (str1 == null || str2 == null) { 829 return str1 == str2; 830 } else if (str1 == str2) { 831 return true; 832 } else if (str1.length() != str2.length()) { 833 return false; 834 } else { 835 return CharSequenceUtils.regionMatches(str1, true, 0, str2, 0, str1.length()); 836 } 837 } 838 839 // IndexOf 840 //----------------------------------------------------------------------- 841 /** 842 * <p>Finds the first index within a CharSequence, handling {@code null}. 843 * This method uses {@link String#indexOf(int, int)} if possible.</p> 844 * 845 * <p>A {@code null} or empty ("") CharSequence will return {@code INDEX_NOT_FOUND (-1)}.</p> 846 * 847 * <pre> 848 * StringUtils.indexOf(null, *) = -1 849 * StringUtils.indexOf("", *) = -1 850 * StringUtils.indexOf("aabaabaa", 'a') = 0 851 * StringUtils.indexOf("aabaabaa", 'b') = 2 852 * </pre> 853 * 854 * @param seq the CharSequence to check, may be null 855 * @param searchChar the character to find 856 * @return the first index of the search character, 857 * -1 if no match or {@code null} string input 858 * @since 2.0 859 * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int) 860 */ 861 public static int indexOf(final CharSequence seq, final int searchChar) { 862 if (isEmpty(seq)) { 863 return INDEX_NOT_FOUND; 864 } 865 return CharSequenceUtils.indexOf(seq, searchChar, 0); 866 } 867 868 /** 869 * <p>Finds the first index within a CharSequence from a start position, 870 * handling {@code null}. 871 * This method uses {@link String#indexOf(int, int)} if possible.</p> 872 * 873 * <p>A {@code null} or empty ("") CharSequence will return {@code (INDEX_NOT_FOUND) -1}. 874 * A negative start position is treated as zero. 875 * A start position greater than the string length returns {@code -1}.</p> 876 * 877 * <pre> 878 * StringUtils.indexOf(null, *, *) = -1 879 * StringUtils.indexOf("", *, *) = -1 880 * StringUtils.indexOf("aabaabaa", 'b', 0) = 2 881 * StringUtils.indexOf("aabaabaa", 'b', 3) = 5 882 * StringUtils.indexOf("aabaabaa", 'b', 9) = -1 883 * StringUtils.indexOf("aabaabaa", 'b', -1) = 2 884 * </pre> 885 * 886 * @param seq the CharSequence to check, may be null 887 * @param searchChar the character to find 888 * @param startPos the start position, negative treated as zero 889 * @return the first index of the search character (always ≥ startPos), 890 * -1 if no match or {@code null} string input 891 * @since 2.0 892 * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int) 893 */ 894 public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) { 895 if (isEmpty(seq)) { 896 return INDEX_NOT_FOUND; 897 } 898 return CharSequenceUtils.indexOf(seq, searchChar, startPos); 899 } 900 901 /** 902 * <p>Finds the first index within a CharSequence, handling {@code null}. 903 * This method uses {@link String#indexOf(String, int)} if possible.</p> 904 * 905 * <p>A {@code null} CharSequence will return {@code -1}.</p> 906 * 907 * <pre> 908 * StringUtils.indexOf(null, *) = -1 909 * StringUtils.indexOf(*, null) = -1 910 * StringUtils.indexOf("", "") = 0 911 * StringUtils.indexOf("", *) = -1 (except when * = "") 912 * StringUtils.indexOf("aabaabaa", "a") = 0 913 * StringUtils.indexOf("aabaabaa", "b") = 2 914 * StringUtils.indexOf("aabaabaa", "ab") = 1 915 * StringUtils.indexOf("aabaabaa", "") = 0 916 * </pre> 917 * 918 * @param seq the CharSequence to check, may be null 919 * @param searchSeq the CharSequence to find, may be null 920 * @return the first index of the search CharSequence, 921 * -1 if no match or {@code null} string input 922 * @since 2.0 923 * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence) 924 */ 925 public static int indexOf(final CharSequence seq, final CharSequence searchSeq) { 926 if (seq == null || searchSeq == null) { 927 return INDEX_NOT_FOUND; 928 } 929 return CharSequenceUtils.indexOf(seq, searchSeq, 0); 930 } 931 932 /** 933 * <p>Finds the first index within a CharSequence, handling {@code null}. 934 * This method uses {@link String#indexOf(String, int)} if possible.</p> 935 * 936 * <p>A {@code null} CharSequence will return {@code -1}. 937 * A negative start position is treated as zero. 938 * An empty ("") search CharSequence always matches. 939 * A start position greater than the string length only matches 940 * an empty search CharSequence.</p> 941 * 942 * <pre> 943 * StringUtils.indexOf(null, *, *) = -1 944 * StringUtils.indexOf(*, null, *) = -1 945 * StringUtils.indexOf("", "", 0) = 0 946 * StringUtils.indexOf("", *, 0) = -1 (except when * = "") 947 * StringUtils.indexOf("aabaabaa", "a", 0) = 0 948 * StringUtils.indexOf("aabaabaa", "b", 0) = 2 949 * StringUtils.indexOf("aabaabaa", "ab", 0) = 1 950 * StringUtils.indexOf("aabaabaa", "b", 3) = 5 951 * StringUtils.indexOf("aabaabaa", "b", 9) = -1 952 * StringUtils.indexOf("aabaabaa", "b", -1) = 2 953 * StringUtils.indexOf("aabaabaa", "", 2) = 2 954 * StringUtils.indexOf("abc", "", 9) = 3 955 * </pre> 956 * 957 * @param seq the CharSequence to check, may be null 958 * @param searchSeq the CharSequence to find, may be null 959 * @param startPos the start position, negative treated as zero 960 * @return the first index of the search CharSequence (always ≥ startPos), 961 * -1 if no match or {@code null} string input 962 * @since 2.0 963 * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int) 964 */ 965 public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 966 if (seq == null || searchSeq == null) { 967 return INDEX_NOT_FOUND; 968 } 969 return CharSequenceUtils.indexOf(seq, searchSeq, startPos); 970 } 971 972 /** 973 * <p>Finds the n-th index within a CharSequence, handling {@code null}. 974 * This method uses {@link String#indexOf(String)} if possible.</p> 975 * 976 * <p>A {@code null} CharSequence will return {@code -1}.</p> 977 * 978 * <pre> 979 * StringUtils.ordinalIndexOf(null, *, *) = -1 980 * StringUtils.ordinalIndexOf(*, null, *) = -1 981 * StringUtils.ordinalIndexOf("", "", *) = 0 982 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0 983 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1 984 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2 985 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5 986 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1 987 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4 988 * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0 989 * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0 990 * </pre> 991 * 992 * <p>Note that 'head(CharSequence str, int n)' may be implemented as: </p> 993 * 994 * <pre> 995 * str.substring(0, lastOrdinalIndexOf(str, "\n", n)) 996 * </pre> 997 * 998 * @param str the CharSequence to check, may be null 999 * @param searchStr the CharSequence to find, may be null 1000 * @param ordinal the n-th {@code searchStr} to find 1001 * @return the n-th index of the search CharSequence, 1002 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 1003 * @since 2.1 1004 * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int) 1005 */ 1006 public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 1007 return ordinalIndexOf(str, searchStr, ordinal, false); 1008 } 1009 1010 /** 1011 * <p>Finds the n-th index within a String, handling {@code null}. 1012 * This method uses {@link String#indexOf(String)} if possible.</p> 1013 * 1014 * <p>A {@code null} CharSequence will return {@code -1}.</p> 1015 * 1016 * @param str the CharSequence to check, may be null 1017 * @param searchStr the CharSequence to find, may be null 1018 * @param ordinal the n-th {@code searchStr} to find 1019 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf() 1020 * @return the n-th index of the search CharSequence, 1021 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 1022 */ 1023 // Shared code between ordinalIndexOf(String,String,int) and lastOrdinalIndexOf(String,String,int) 1024 private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) { 1025 if (str == null || searchStr == null || ordinal <= 0) { 1026 return INDEX_NOT_FOUND; 1027 } 1028 if (searchStr.length() == 0) { 1029 return lastIndex ? str.length() : 0; 1030 } 1031 int found = 0; 1032 int index = lastIndex ? str.length() : INDEX_NOT_FOUND; 1033 do { 1034 if (lastIndex) { 1035 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); 1036 } else { 1037 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); 1038 } 1039 if (index < 0) { 1040 return index; 1041 } 1042 found++; 1043 } while (found < ordinal); 1044 return index; 1045 } 1046 1047 /** 1048 * <p>Case in-sensitive find of the first index within a CharSequence.</p> 1049 * 1050 * <p>A {@code null} CharSequence will return {@code -1}. 1051 * A negative start position is treated as zero. 1052 * An empty ("") search CharSequence always matches. 1053 * A start position greater than the string length only matches 1054 * an empty search CharSequence.</p> 1055 * 1056 * <pre> 1057 * StringUtils.indexOfIgnoreCase(null, *) = -1 1058 * StringUtils.indexOfIgnoreCase(*, null) = -1 1059 * StringUtils.indexOfIgnoreCase("", "") = 0 1060 * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0 1061 * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2 1062 * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1 1063 * </pre> 1064 * 1065 * @param str the CharSequence to check, may be null 1066 * @param searchStr the CharSequence to find, may be null 1067 * @return the first index of the search CharSequence, 1068 * -1 if no match or {@code null} string input 1069 * @since 2.5 1070 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence) 1071 */ 1072 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 1073 return indexOfIgnoreCase(str, searchStr, 0); 1074 } 1075 1076 /** 1077 * <p>Case in-sensitive find of the first index within a CharSequence 1078 * from the specified position.</p> 1079 * 1080 * <p>A {@code null} CharSequence will return {@code -1}. 1081 * A negative start position is treated as zero. 1082 * An empty ("") search CharSequence always matches. 1083 * A start position greater than the string length only matches 1084 * an empty search CharSequence.</p> 1085 * 1086 * <pre> 1087 * StringUtils.indexOfIgnoreCase(null, *, *) = -1 1088 * StringUtils.indexOfIgnoreCase(*, null, *) = -1 1089 * StringUtils.indexOfIgnoreCase("", "", 0) = 0 1090 * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 1091 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 1092 * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 1093 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 1094 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 1095 * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 1096 * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2 1097 * StringUtils.indexOfIgnoreCase("abc", "", 9) = 3 1098 * </pre> 1099 * 1100 * @param str the CharSequence to check, may be null 1101 * @param searchStr the CharSequence to find, may be null 1102 * @param startPos the start position, negative treated as zero 1103 * @return the first index of the search CharSequence (always ≥ startPos), 1104 * -1 if no match or {@code null} string input 1105 * @since 2.5 1106 * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int) 1107 */ 1108 public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) { 1109 if (str == null || searchStr == null) { 1110 return INDEX_NOT_FOUND; 1111 } 1112 if (startPos < 0) { 1113 startPos = 0; 1114 } 1115 final int endLimit = str.length() - searchStr.length() + 1; 1116 if (startPos > endLimit) { 1117 return INDEX_NOT_FOUND; 1118 } 1119 if (searchStr.length() == 0) { 1120 return startPos; 1121 } 1122 for (int i = startPos; i < endLimit; i++) { 1123 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) { 1124 return i; 1125 } 1126 } 1127 return INDEX_NOT_FOUND; 1128 } 1129 1130 // LastIndexOf 1131 //----------------------------------------------------------------------- 1132 /** 1133 * <p>Finds the last index within a CharSequence, handling {@code null}. 1134 * This method uses {@link String#lastIndexOf(int)} if possible.</p> 1135 * 1136 * <p>A {@code null} or empty ("") CharSequence will return {@code -1}.</p> 1137 * 1138 * <pre> 1139 * StringUtils.lastIndexOf(null, *) = -1 1140 * StringUtils.lastIndexOf("", *) = -1 1141 * StringUtils.lastIndexOf("aabaabaa", 'a') = 7 1142 * StringUtils.lastIndexOf("aabaabaa", 'b') = 5 1143 * </pre> 1144 * 1145 * @param seq the CharSequence to check, may be null 1146 * @param searchChar the character to find 1147 * @return the last index of the search character, 1148 * -1 if no match or {@code null} string input 1149 * @since 2.0 1150 * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int) 1151 */ 1152 public static int lastIndexOf(final CharSequence seq, final int searchChar) { 1153 if (isEmpty(seq)) { 1154 return INDEX_NOT_FOUND; 1155 } 1156 return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length()); 1157 } 1158 1159 /** 1160 * <p>Finds the last index within a CharSequence from a start position, 1161 * handling {@code null}. 1162 * This method uses {@link String#lastIndexOf(int, int)} if possible.</p> 1163 * 1164 * <p>A {@code null} or empty ("") CharSequence will return {@code -1}. 1165 * A negative start position returns {@code -1}. 1166 * A start position greater than the string length searches the whole string. 1167 * The search starts at the startPos and works backwards; matches starting after the start 1168 * position are ignored. 1169 * </p> 1170 * 1171 * <pre> 1172 * StringUtils.lastIndexOf(null, *, *) = -1 1173 * StringUtils.lastIndexOf("", *, *) = -1 1174 * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5 1175 * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2 1176 * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1 1177 * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5 1178 * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1 1179 * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0 1180 * </pre> 1181 * 1182 * @param seq the CharSequence to check, may be null 1183 * @param searchChar the character to find 1184 * @param startPos the start position 1185 * @return the last index of the search character (always ≤ startPos), 1186 * -1 if no match or {@code null} string input 1187 * @since 2.0 1188 * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int) 1189 */ 1190 public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) { 1191 if (isEmpty(seq)) { 1192 return INDEX_NOT_FOUND; 1193 } 1194 return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos); 1195 } 1196 1197 /** 1198 * <p>Finds the last index within a CharSequence, handling {@code null}. 1199 * This method uses {@link String#lastIndexOf(String)} if possible.</p> 1200 * 1201 * <p>A {@code null} CharSequence will return {@code -1}.</p> 1202 * 1203 * <pre> 1204 * StringUtils.lastIndexOf(null, *) = -1 1205 * StringUtils.lastIndexOf(*, null) = -1 1206 * StringUtils.lastIndexOf("", "") = 0 1207 * StringUtils.lastIndexOf("aabaabaa", "a") = 7 1208 * StringUtils.lastIndexOf("aabaabaa", "b") = 5 1209 * StringUtils.lastIndexOf("aabaabaa", "ab") = 4 1210 * StringUtils.lastIndexOf("aabaabaa", "") = 8 1211 * </pre> 1212 * 1213 * @param seq the CharSequence to check, may be null 1214 * @param searchSeq the CharSequence to find, may be null 1215 * @return the last index of the search String, 1216 * -1 if no match or {@code null} string input 1217 * @since 2.0 1218 * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence) 1219 */ 1220 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) { 1221 if (seq == null || searchSeq == null) { 1222 return INDEX_NOT_FOUND; 1223 } 1224 return CharSequenceUtils.lastIndexOf(seq, searchSeq, seq.length()); 1225 } 1226 1227 /** 1228 * <p>Finds the n-th last index within a String, handling {@code null}. 1229 * This method uses {@link String#lastIndexOf(String)}.</p> 1230 * 1231 * <p>A {@code null} String will return {@code -1}.</p> 1232 * 1233 * <pre> 1234 * StringUtils.lastOrdinalIndexOf(null, *, *) = -1 1235 * StringUtils.lastOrdinalIndexOf(*, null, *) = -1 1236 * StringUtils.lastOrdinalIndexOf("", "", *) = 0 1237 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7 1238 * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6 1239 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5 1240 * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2 1241 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4 1242 * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1 1243 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8 1244 * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8 1245 * </pre> 1246 * 1247 * <p>Note that 'tail(CharSequence str, int n)' may be implemented as: </p> 1248 * 1249 * <pre> 1250 * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1) 1251 * </pre> 1252 * 1253 * @param str the CharSequence to check, may be null 1254 * @param searchStr the CharSequence to find, may be null 1255 * @param ordinal the n-th last {@code searchStr} to find 1256 * @return the n-th last index of the search CharSequence, 1257 * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input 1258 * @since 2.5 1259 * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int) 1260 */ 1261 public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) { 1262 return ordinalIndexOf(str, searchStr, ordinal, true); 1263 } 1264 1265 /** 1266 * <p>Finds the last index within a CharSequence, handling {@code null}. 1267 * This method uses {@link String#lastIndexOf(String, int)} if possible.</p> 1268 * 1269 * <p>A {@code null} CharSequence will return {@code -1}. 1270 * A negative start position returns {@code -1}. 1271 * An empty ("") search CharSequence always matches unless the start position is negative. 1272 * A start position greater than the string length searches the whole string. 1273 * The search starts at the startPos and works backwards; matches starting after the start 1274 * position are ignored. 1275 * </p> 1276 * 1277 * <pre> 1278 * StringUtils.lastIndexOf(null, *, *) = -1 1279 * StringUtils.lastIndexOf(*, null, *) = -1 1280 * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7 1281 * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5 1282 * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4 1283 * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5 1284 * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1 1285 * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0 1286 * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1 1287 * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1 1288 * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2 1289 * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = -1 1290 * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2 1291 * </pre> 1292 * 1293 * @param seq the CharSequence to check, may be null 1294 * @param searchSeq the CharSequence to find, may be null 1295 * @param startPos the start position, negative treated as zero 1296 * @return the last index of the search CharSequence (always ≤ startPos), 1297 * -1 if no match or {@code null} string input 1298 * @since 2.0 1299 * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int) 1300 */ 1301 public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) { 1302 if (seq == null || searchSeq == null) { 1303 return INDEX_NOT_FOUND; 1304 } 1305 return CharSequenceUtils.lastIndexOf(seq, searchSeq, startPos); 1306 } 1307 1308 /** 1309 * <p>Case in-sensitive find of the last index within a CharSequence.</p> 1310 * 1311 * <p>A {@code null} CharSequence will return {@code -1}. 1312 * A negative start position returns {@code -1}. 1313 * An empty ("") search CharSequence always matches unless the start position is negative. 1314 * A start position greater than the string length searches the whole string.</p> 1315 * 1316 * <pre> 1317 * StringUtils.lastIndexOfIgnoreCase(null, *) = -1 1318 * StringUtils.lastIndexOfIgnoreCase(*, null) = -1 1319 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7 1320 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5 1321 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4 1322 * </pre> 1323 * 1324 * @param str the CharSequence to check, may be null 1325 * @param searchStr the CharSequence to find, may be null 1326 * @return the first index of the search CharSequence, 1327 * -1 if no match or {@code null} string input 1328 * @since 2.5 1329 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence) 1330 */ 1331 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { 1332 if (str == null || searchStr == null) { 1333 return INDEX_NOT_FOUND; 1334 } 1335 return lastIndexOfIgnoreCase(str, searchStr, str.length()); 1336 } 1337 1338 /** 1339 * <p>Case in-sensitive find of the last index within a CharSequence 1340 * from the specified position.</p> 1341 * 1342 * <p>A {@code null} CharSequence will return {@code -1}. 1343 * A negative start position returns {@code -1}. 1344 * An empty ("") search CharSequence always matches unless the start position is negative. 1345 * A start position greater than the string length searches the whole string. 1346 * The search starts at the startPos and works backwards; matches starting after the start 1347 * position are ignored. 1348 * </p> 1349 * 1350 * <pre> 1351 * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1 1352 * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1 1353 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7 1354 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5 1355 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4 1356 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5 1357 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1 1358 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0 1359 * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1 1360 * </pre> 1361 * 1362 * @param str the CharSequence to check, may be null 1363 * @param searchStr the CharSequence to find, may be null 1364 * @param startPos the start position 1365 * @return the last index of the search CharSequence (always ≤ startPos), 1366 * -1 if no match or {@code null} input 1367 * @since 2.5 1368 * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int) 1369 */ 1370 public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) { 1371 if (str == null || searchStr == null) { 1372 return INDEX_NOT_FOUND; 1373 } 1374 if (startPos > str.length() - searchStr.length()) { 1375 startPos = str.length() - searchStr.length(); 1376 } 1377 if (startPos < 0) { 1378 return INDEX_NOT_FOUND; 1379 } 1380 if (searchStr.length() == 0) { 1381 return startPos; 1382 } 1383 1384 for (int i = startPos; i >= 0; i--) { 1385 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) { 1386 return i; 1387 } 1388 } 1389 return INDEX_NOT_FOUND; 1390 } 1391 1392 // Contains 1393 //----------------------------------------------------------------------- 1394 /** 1395 * <p>Checks if CharSequence contains a search character, handling {@code null}. 1396 * This method uses {@link String#indexOf(int)} if possible.</p> 1397 * 1398 * <p>A {@code null} or empty ("") CharSequence will return {@code false}.</p> 1399 * 1400 * <pre> 1401 * StringUtils.contains(null, *) = false 1402 * StringUtils.contains("", *) = false 1403 * StringUtils.contains("abc", 'a') = true 1404 * StringUtils.contains("abc", 'z') = false 1405 * </pre> 1406 * 1407 * @param seq the CharSequence to check, may be null 1408 * @param searchChar the character to find 1409 * @return true if the CharSequence contains the search character, 1410 * false if not or {@code null} string input 1411 * @since 2.0 1412 * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int) 1413 */ 1414 public static boolean contains(final CharSequence seq, final int searchChar) { 1415 if (isEmpty(seq)) { 1416 return false; 1417 } 1418 return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0; 1419 } 1420 1421 /** 1422 * <p>Checks if CharSequence contains a search CharSequence, handling {@code null}. 1423 * This method uses {@link String#indexOf(String)} if possible.</p> 1424 * 1425 * <p>A {@code null} CharSequence will return {@code false}.</p> 1426 * 1427 * <pre> 1428 * StringUtils.contains(null, *) = false 1429 * StringUtils.contains(*, null) = false 1430 * StringUtils.contains("", "") = true 1431 * StringUtils.contains("abc", "") = true 1432 * StringUtils.contains("abc", "a") = true 1433 * StringUtils.contains("abc", "z") = false 1434 * </pre> 1435 * 1436 * @param seq the CharSequence to check, may be null 1437 * @param searchSeq the CharSequence to find, may be null 1438 * @return true if the CharSequence contains the search CharSequence, 1439 * false if not or {@code null} string input 1440 * @since 2.0 1441 * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence) 1442 */ 1443 public static boolean contains(final CharSequence seq, final CharSequence searchSeq) { 1444 if (seq == null || searchSeq == null) { 1445 return false; 1446 } 1447 return CharSequenceUtils.indexOf(seq, searchSeq, 0) >= 0; 1448 } 1449 1450 /** 1451 * <p>Checks if CharSequence contains a search CharSequence irrespective of case, 1452 * handling {@code null}. Case-insensitivity is defined as by 1453 * {@link String#equalsIgnoreCase(String)}. 1454 * 1455 * <p>A {@code null} CharSequence will return {@code false}.</p> 1456 * 1457 * <pre> 1458 * StringUtils.contains(null, *) = false 1459 * StringUtils.contains(*, null) = false 1460 * StringUtils.contains("", "") = true 1461 * StringUtils.contains("abc", "") = true 1462 * StringUtils.contains("abc", "a") = true 1463 * StringUtils.contains("abc", "z") = false 1464 * StringUtils.contains("abc", "A") = true 1465 * StringUtils.contains("abc", "Z") = false 1466 * </pre> 1467 * 1468 * @param str the CharSequence to check, may be null 1469 * @param searchStr the CharSequence to find, may be null 1470 * @return true if the CharSequence contains the search CharSequence irrespective of 1471 * case or false if not or {@code null} string input 1472 * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence) 1473 */ 1474 public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) { 1475 if (str == null || searchStr == null) { 1476 return false; 1477 } 1478 final int len = searchStr.length(); 1479 final int max = str.length() - len; 1480 for (int i = 0; i <= max; i++) { 1481 if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, len)) { 1482 return true; 1483 } 1484 } 1485 return false; 1486 } 1487 1488 /** 1489 * Check whether the given CharSequence contains any whitespace characters. 1490 * @param seq the CharSequence to check (may be {@code null}) 1491 * @return {@code true} if the CharSequence is not empty and 1492 * contains at least 1 whitespace character 1493 * @see java.lang.Character#isWhitespace 1494 * @since 3.0 1495 */ 1496 // From org.springframework.util.StringUtils, under Apache License 2.0 1497 public static boolean containsWhitespace(final CharSequence seq) { 1498 if (isEmpty(seq)) { 1499 return false; 1500 } 1501 final int strLen = seq.length(); 1502 for (int i = 0; i < strLen; i++) { 1503 if (Character.isWhitespace(seq.charAt(i))) { 1504 return true; 1505 } 1506 } 1507 return false; 1508 } 1509 1510 // IndexOfAny chars 1511 //----------------------------------------------------------------------- 1512 /** 1513 * <p>Search a CharSequence to find the first index of any 1514 * character in the given set of characters.</p> 1515 * 1516 * <p>A {@code null} String will return {@code -1}. 1517 * A {@code null} or zero length search array will return {@code -1}.</p> 1518 * 1519 * <pre> 1520 * StringUtils.indexOfAny(null, *) = -1 1521 * StringUtils.indexOfAny("", *) = -1 1522 * StringUtils.indexOfAny(*, null) = -1 1523 * StringUtils.indexOfAny(*, []) = -1 1524 * StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0 1525 * StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3 1526 * StringUtils.indexOfAny("aba", ['z']) = -1 1527 * </pre> 1528 * 1529 * @param cs the CharSequence to check, may be null 1530 * @param searchChars the chars to search for, may be null 1531 * @return the index of any of the chars, -1 if no match or null input 1532 * @since 2.0 1533 * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...) 1534 */ 1535 public static int indexOfAny(final CharSequence cs, final char... searchChars) { 1536 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 1537 return INDEX_NOT_FOUND; 1538 } 1539 final int csLen = cs.length(); 1540 final int csLast = csLen - 1; 1541 final int searchLen = searchChars.length; 1542 final int searchLast = searchLen - 1; 1543 for (int i = 0; i < csLen; i++) { 1544 final char ch = cs.charAt(i); 1545 for (int j = 0; j < searchLen; j++) { 1546 if (searchChars[j] == ch) { 1547 if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) { 1548 // ch is a supplementary character 1549 if (searchChars[j + 1] == cs.charAt(i + 1)) { 1550 return i; 1551 } 1552 } else { 1553 return i; 1554 } 1555 } 1556 } 1557 } 1558 return INDEX_NOT_FOUND; 1559 } 1560 1561 /** 1562 * <p>Search a CharSequence to find the first index of any 1563 * character in the given set of characters.</p> 1564 * 1565 * <p>A {@code null} String will return {@code -1}. 1566 * A {@code null} search string will return {@code -1}.</p> 1567 * 1568 * <pre> 1569 * StringUtils.indexOfAny(null, *) = -1 1570 * StringUtils.indexOfAny("", *) = -1 1571 * StringUtils.indexOfAny(*, null) = -1 1572 * StringUtils.indexOfAny(*, "") = -1 1573 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0 1574 * StringUtils.indexOfAny("zzabyycdxx", "by") = 3 1575 * StringUtils.indexOfAny("aba","z") = -1 1576 * </pre> 1577 * 1578 * @param cs the CharSequence to check, may be null 1579 * @param searchChars the chars to search for, may be null 1580 * @return the index of any of the chars, -1 if no match or null input 1581 * @since 2.0 1582 * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String) 1583 */ 1584 public static int indexOfAny(final CharSequence cs, final String searchChars) { 1585 if (isEmpty(cs) || isEmpty(searchChars)) { 1586 return INDEX_NOT_FOUND; 1587 } 1588 return indexOfAny(cs, searchChars.toCharArray()); 1589 } 1590 1591 // ContainsAny 1592 //----------------------------------------------------------------------- 1593 /** 1594 * <p>Checks if the CharSequence contains any character in the given 1595 * set of characters.</p> 1596 * 1597 * <p>A {@code null} CharSequence will return {@code false}. 1598 * A {@code null} or zero length search array will return {@code false}.</p> 1599 * 1600 * <pre> 1601 * StringUtils.containsAny(null, *) = false 1602 * StringUtils.containsAny("", *) = false 1603 * StringUtils.containsAny(*, null) = false 1604 * StringUtils.containsAny(*, []) = false 1605 * StringUtils.containsAny("zzabyycdxx",['z','a']) = true 1606 * StringUtils.containsAny("zzabyycdxx",['b','y']) = true 1607 * StringUtils.containsAny("aba", ['z']) = false 1608 * </pre> 1609 * 1610 * @param cs the CharSequence to check, may be null 1611 * @param searchChars the chars to search for, may be null 1612 * @return the {@code true} if any of the chars are found, 1613 * {@code false} if no match or null input 1614 * @since 2.4 1615 * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...) 1616 */ 1617 public static boolean containsAny(final CharSequence cs, final char... searchChars) { 1618 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 1619 return false; 1620 } 1621 final int csLength = cs.length(); 1622 final int searchLength = searchChars.length; 1623 final int csLast = csLength - 1; 1624 final int searchLast = searchLength - 1; 1625 for (int i = 0; i < csLength; i++) { 1626 final char ch = cs.charAt(i); 1627 for (int j = 0; j < searchLength; j++) { 1628 if (searchChars[j] == ch) { 1629 if (Character.isHighSurrogate(ch)) { 1630 if (j == searchLast) { 1631 // missing low surrogate, fine, like String.indexOf(String) 1632 return true; 1633 } 1634 if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1635 return true; 1636 } 1637 } else { 1638 // ch is in the Basic Multilingual Plane 1639 return true; 1640 } 1641 } 1642 } 1643 } 1644 return false; 1645 } 1646 1647 /** 1648 * <p> 1649 * Checks if the CharSequence contains any character in the given set of characters. 1650 * </p> 1651 * 1652 * <p> 1653 * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return 1654 * {@code false}. 1655 * </p> 1656 * 1657 * <pre> 1658 * StringUtils.containsAny(null, *) = false 1659 * StringUtils.containsAny("", *) = false 1660 * StringUtils.containsAny(*, null) = false 1661 * StringUtils.containsAny(*, "") = false 1662 * StringUtils.containsAny("zzabyycdxx", "za") = true 1663 * StringUtils.containsAny("zzabyycdxx", "by") = true 1664 * StringUtils.containsAny("aba","z") = false 1665 * </pre> 1666 * 1667 * @param cs 1668 * the CharSequence to check, may be null 1669 * @param searchChars 1670 * the chars to search for, may be null 1671 * @return the {@code true} if any of the chars are found, {@code false} if no match or null input 1672 * @since 2.4 1673 * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence) 1674 */ 1675 public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) { 1676 if (searchChars == null) { 1677 return false; 1678 } 1679 return containsAny(cs, CharSequenceUtils.toCharArray(searchChars)); 1680 } 1681 1682 // IndexOfAnyBut chars 1683 //----------------------------------------------------------------------- 1684 /** 1685 * <p>Searches a CharSequence to find the first index of any 1686 * character not in the given set of characters.</p> 1687 * 1688 * <p>A {@code null} CharSequence will return {@code -1}. 1689 * A {@code null} or zero length search array will return {@code -1}.</p> 1690 * 1691 * <pre> 1692 * StringUtils.indexOfAnyBut(null, *) = -1 1693 * StringUtils.indexOfAnyBut("", *) = -1 1694 * StringUtils.indexOfAnyBut(*, null) = -1 1695 * StringUtils.indexOfAnyBut(*, []) = -1 1696 * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3 1697 * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0 1698 * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1 1699 1700 * </pre> 1701 * 1702 * @param cs the CharSequence to check, may be null 1703 * @param searchChars the chars to search for, may be null 1704 * @return the index of any of the chars, -1 if no match or null input 1705 * @since 2.0 1706 * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...) 1707 */ 1708 public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) { 1709 if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) { 1710 return INDEX_NOT_FOUND; 1711 } 1712 final int csLen = cs.length(); 1713 final int csLast = csLen - 1; 1714 final int searchLen = searchChars.length; 1715 final int searchLast = searchLen - 1; 1716 outer: 1717 for (int i = 0; i < csLen; i++) { 1718 final char ch = cs.charAt(i); 1719 for (int j = 0; j < searchLen; j++) { 1720 if (searchChars[j] == ch) { 1721 if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) { 1722 if (searchChars[j + 1] == cs.charAt(i + 1)) { 1723 continue outer; 1724 } 1725 } else { 1726 continue outer; 1727 } 1728 } 1729 } 1730 return i; 1731 } 1732 return INDEX_NOT_FOUND; 1733 } 1734 1735 /** 1736 * <p>Search a CharSequence to find the first index of any 1737 * character not in the given set of characters.</p> 1738 * 1739 * <p>A {@code null} CharSequence will return {@code -1}. 1740 * A {@code null} or empty search string will return {@code -1}.</p> 1741 * 1742 * <pre> 1743 * StringUtils.indexOfAnyBut(null, *) = -1 1744 * StringUtils.indexOfAnyBut("", *) = -1 1745 * StringUtils.indexOfAnyBut(*, null) = -1 1746 * StringUtils.indexOfAnyBut(*, "") = -1 1747 * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3 1748 * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1 1749 * StringUtils.indexOfAnyBut("aba","ab") = -1 1750 * </pre> 1751 * 1752 * @param seq the CharSequence to check, may be null 1753 * @param searchChars the chars to search for, may be null 1754 * @return the index of any of the chars, -1 if no match or null input 1755 * @since 2.0 1756 * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence) 1757 */ 1758 public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) { 1759 if (isEmpty(seq) || isEmpty(searchChars)) { 1760 return INDEX_NOT_FOUND; 1761 } 1762 final int strLen = seq.length(); 1763 for (int i = 0; i < strLen; i++) { 1764 final char ch = seq.charAt(i); 1765 final boolean chFound = CharSequenceUtils.indexOf(searchChars, ch, 0) >= 0; 1766 if (i + 1 < strLen && Character.isHighSurrogate(ch)) { 1767 final char ch2 = seq.charAt(i + 1); 1768 if (chFound && CharSequenceUtils.indexOf(searchChars, ch2, 0) < 0) { 1769 return i; 1770 } 1771 } else { 1772 if (!chFound) { 1773 return i; 1774 } 1775 } 1776 } 1777 return INDEX_NOT_FOUND; 1778 } 1779 1780 // ContainsOnly 1781 //----------------------------------------------------------------------- 1782 /** 1783 * <p>Checks if the CharSequence contains only certain characters.</p> 1784 * 1785 * <p>A {@code null} CharSequence will return {@code false}. 1786 * A {@code null} valid character array will return {@code false}. 1787 * An empty CharSequence (length()=0) always returns {@code true}.</p> 1788 * 1789 * <pre> 1790 * StringUtils.containsOnly(null, *) = false 1791 * StringUtils.containsOnly(*, null) = false 1792 * StringUtils.containsOnly("", *) = true 1793 * StringUtils.containsOnly("ab", '') = false 1794 * StringUtils.containsOnly("abab", 'abc') = true 1795 * StringUtils.containsOnly("ab1", 'abc') = false 1796 * StringUtils.containsOnly("abz", 'abc') = false 1797 * </pre> 1798 * 1799 * @param cs the String to check, may be null 1800 * @param valid an array of valid chars, may be null 1801 * @return true if it only contains valid chars and is non-null 1802 * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...) 1803 */ 1804 public static boolean containsOnly(final CharSequence cs, final char... valid) { 1805 // All these pre-checks are to maintain API with an older version 1806 if (valid == null || cs == null) { 1807 return false; 1808 } 1809 if (cs.length() == 0) { 1810 return true; 1811 } 1812 if (valid.length == 0) { 1813 return false; 1814 } 1815 return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND; 1816 } 1817 1818 /** 1819 * <p>Checks if the CharSequence contains only certain characters.</p> 1820 * 1821 * <p>A {@code null} CharSequence will return {@code false}. 1822 * A {@code null} valid character String will return {@code false}. 1823 * An empty String (length()=0) always returns {@code true}.</p> 1824 * 1825 * <pre> 1826 * StringUtils.containsOnly(null, *) = false 1827 * StringUtils.containsOnly(*, null) = false 1828 * StringUtils.containsOnly("", *) = true 1829 * StringUtils.containsOnly("ab", "") = false 1830 * StringUtils.containsOnly("abab", "abc") = true 1831 * StringUtils.containsOnly("ab1", "abc") = false 1832 * StringUtils.containsOnly("abz", "abc") = false 1833 * </pre> 1834 * 1835 * @param cs the CharSequence to check, may be null 1836 * @param validChars a String of valid chars, may be null 1837 * @return true if it only contains valid chars and is non-null 1838 * @since 2.0 1839 * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String) 1840 */ 1841 public static boolean containsOnly(final CharSequence cs, final String validChars) { 1842 if (cs == null || validChars == null) { 1843 return false; 1844 } 1845 return containsOnly(cs, validChars.toCharArray()); 1846 } 1847 1848 // ContainsNone 1849 //----------------------------------------------------------------------- 1850 /** 1851 * <p>Checks that the CharSequence does not contain certain characters.</p> 1852 * 1853 * <p>A {@code null} CharSequence will return {@code true}. 1854 * A {@code null} invalid character array will return {@code true}. 1855 * An empty CharSequence (length()=0) always returns true.</p> 1856 * 1857 * <pre> 1858 * StringUtils.containsNone(null, *) = true 1859 * StringUtils.containsNone(*, null) = true 1860 * StringUtils.containsNone("", *) = true 1861 * StringUtils.containsNone("ab", '') = true 1862 * StringUtils.containsNone("abab", 'xyz') = true 1863 * StringUtils.containsNone("ab1", 'xyz') = true 1864 * StringUtils.containsNone("abz", 'xyz') = false 1865 * </pre> 1866 * 1867 * @param cs the CharSequence to check, may be null 1868 * @param searchChars an array of invalid chars, may be null 1869 * @return true if it contains none of the invalid chars, or is null 1870 * @since 2.0 1871 * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...) 1872 */ 1873 public static boolean containsNone(final CharSequence cs, final char... searchChars) { 1874 if (cs == null || searchChars == null) { 1875 return true; 1876 } 1877 final int csLen = cs.length(); 1878 final int csLast = csLen - 1; 1879 final int searchLen = searchChars.length; 1880 final int searchLast = searchLen - 1; 1881 for (int i = 0; i < csLen; i++) { 1882 final char ch = cs.charAt(i); 1883 for (int j = 0; j < searchLen; j++) { 1884 if (searchChars[j] == ch) { 1885 if (Character.isHighSurrogate(ch)) { 1886 if (j == searchLast) { 1887 // missing low surrogate, fine, like String.indexOf(String) 1888 return false; 1889 } 1890 if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) { 1891 return false; 1892 } 1893 } else { 1894 // ch is in the Basic Multilingual Plane 1895 return false; 1896 } 1897 } 1898 } 1899 } 1900 return true; 1901 } 1902 1903 /** 1904 * <p>Checks that the CharSequence does not contain certain characters.</p> 1905 * 1906 * <p>A {@code null} CharSequence will return {@code true}. 1907 * A {@code null} invalid character array will return {@code true}. 1908 * An empty String ("") always returns true.</p> 1909 * 1910 * <pre> 1911 * StringUtils.containsNone(null, *) = true 1912 * StringUtils.containsNone(*, null) = true 1913 * StringUtils.containsNone("", *) = true 1914 * StringUtils.containsNone("ab", "") = true 1915 * StringUtils.containsNone("abab", "xyz") = true 1916 * StringUtils.containsNone("ab1", "xyz") = true 1917 * StringUtils.containsNone("abz", "xyz") = false 1918 * </pre> 1919 * 1920 * @param cs the CharSequence to check, may be null 1921 * @param invalidChars a String of invalid chars, may be null 1922 * @return true if it contains none of the invalid chars, or is null 1923 * @since 2.0 1924 * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String) 1925 */ 1926 public static boolean containsNone(final CharSequence cs, final String invalidChars) { 1927 if (cs == null || invalidChars == null) { 1928 return true; 1929 } 1930 return containsNone(cs, invalidChars.toCharArray()); 1931 } 1932 1933 // IndexOfAny strings 1934 //----------------------------------------------------------------------- 1935 /** 1936 * <p>Find the first index of any of a set of potential substrings.</p> 1937 * 1938 * <p>A {@code null} CharSequence will return {@code -1}. 1939 * A {@code null} or zero length search array will return {@code -1}. 1940 * A {@code null} search array entry will be ignored, but a search 1941 * array containing "" will return {@code 0} if {@code str} is not 1942 * null. This method uses {@link String#indexOf(String)} if possible.</p> 1943 * 1944 * <pre> 1945 * StringUtils.indexOfAny(null, *) = -1 1946 * StringUtils.indexOfAny(*, null) = -1 1947 * StringUtils.indexOfAny(*, []) = -1 1948 * StringUtils.indexOfAny("zzabyycdxx", ["ab","cd"]) = 2 1949 * StringUtils.indexOfAny("zzabyycdxx", ["cd","ab"]) = 2 1950 * StringUtils.indexOfAny("zzabyycdxx", ["mn","op"]) = -1 1951 * StringUtils.indexOfAny("zzabyycdxx", ["zab","aby"]) = 1 1952 * StringUtils.indexOfAny("zzabyycdxx", [""]) = 0 1953 * StringUtils.indexOfAny("", [""]) = 0 1954 * StringUtils.indexOfAny("", ["a"]) = -1 1955 * </pre> 1956 * 1957 * @param str the CharSequence to check, may be null 1958 * @param searchStrs the CharSequences to search for, may be null 1959 * @return the first index of any of the searchStrs in str, -1 if no match 1960 * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...) 1961 */ 1962 public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) { 1963 if (str == null || searchStrs == null) { 1964 return INDEX_NOT_FOUND; 1965 } 1966 final int sz = searchStrs.length; 1967 1968 // String's can't have a MAX_VALUEth index. 1969 int ret = Integer.MAX_VALUE; 1970 1971 int tmp = 0; 1972 for (int i = 0; i < sz; i++) { 1973 final CharSequence search = searchStrs[i]; 1974 if (search == null) { 1975 continue; 1976 } 1977 tmp = CharSequenceUtils.indexOf(str, search, 0); 1978 if (tmp == INDEX_NOT_FOUND) { 1979 continue; 1980 } 1981 1982 if (tmp < ret) { 1983 ret = tmp; 1984 } 1985 } 1986 1987 return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret; 1988 } 1989 1990 /** 1991 * <p>Find the latest index of any of a set of potential substrings.</p> 1992 * 1993 * <p>A {@code null} CharSequence will return {@code -1}. 1994 * A {@code null} search array will return {@code -1}. 1995 * A {@code null} or zero length search array entry will be ignored, 1996 * but a search array containing "" will return the length of {@code str} 1997 * if {@code str} is not null. This method uses {@link String#indexOf(String)} if possible</p> 1998 * 1999 * <pre> 2000 * StringUtils.lastIndexOfAny(null, *) = -1 2001 * StringUtils.lastIndexOfAny(*, null) = -1 2002 * StringUtils.lastIndexOfAny(*, []) = -1 2003 * StringUtils.lastIndexOfAny(*, [null]) = -1 2004 * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab","cd"]) = 6 2005 * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd","ab"]) = 6 2006 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1 2007 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1 2008 * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn",""]) = 10 2009 * </pre> 2010 * 2011 * @param str the CharSequence to check, may be null 2012 * @param searchStrs the CharSequences to search for, may be null 2013 * @return the last index of any of the CharSequences, -1 if no match 2014 * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence) 2015 */ 2016 public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) { 2017 if (str == null || searchStrs == null) { 2018 return INDEX_NOT_FOUND; 2019 } 2020 final int sz = searchStrs.length; 2021 int ret = INDEX_NOT_FOUND; 2022 int tmp = 0; 2023 for (int i = 0; i < sz; i++) { 2024 final CharSequence search = searchStrs[i]; 2025 if (search == null) { 2026 continue; 2027 } 2028 tmp = CharSequenceUtils.lastIndexOf(str, search, str.length()); 2029 if (tmp > ret) { 2030 ret = tmp; 2031 } 2032 } 2033 return ret; 2034 } 2035 2036 // Substring 2037 //----------------------------------------------------------------------- 2038 /** 2039 * <p>Gets a substring from the specified String avoiding exceptions.</p> 2040 * 2041 * <p>A negative start position can be used to start {@code n} 2042 * characters from the end of the String.</p> 2043 * 2044 * <p>A {@code null} String will return {@code null}. 2045 * An empty ("") String will return "".</p> 2046 * 2047 * <pre> 2048 * StringUtils.substring(null, *) = null 2049 * StringUtils.substring("", *) = "" 2050 * StringUtils.substring("abc", 0) = "abc" 2051 * StringUtils.substring("abc", 2) = "c" 2052 * StringUtils.substring("abc", 4) = "" 2053 * StringUtils.substring("abc", -2) = "bc" 2054 * StringUtils.substring("abc", -4) = "abc" 2055 * </pre> 2056 * 2057 * @param str the String to get the substring from, may be null 2058 * @param start the position to start from, negative means 2059 * count back from the end of the String by this many characters 2060 * @return substring from start position, {@code null} if null String input 2061 */ 2062 public static String substring(final String str, int start) { 2063 if (str == null) { 2064 return null; 2065 } 2066 2067 // handle negatives, which means last n characters 2068 if (start < 0) { 2069 start = str.length() + start; // remember start is negative 2070 } 2071 2072 if (start < 0) { 2073 start = 0; 2074 } 2075 if (start > str.length()) { 2076 return EMPTY; 2077 } 2078 2079 return str.substring(start); 2080 } 2081 2082 /** 2083 * <p>Gets a substring from the specified String avoiding exceptions.</p> 2084 * 2085 * <p>A negative start position can be used to start/end {@code n} 2086 * characters from the end of the String.</p> 2087 * 2088 * <p>The returned substring starts with the character in the {@code start} 2089 * position and ends before the {@code end} position. All position counting is 2090 * zero-based -- i.e., to start at the beginning of the string use 2091 * {@code start = 0}. Negative start and end positions can be used to 2092 * specify offsets relative to the end of the String.</p> 2093 * 2094 * <p>If {@code start} is not strictly to the left of {@code end}, "" 2095 * is returned.</p> 2096 * 2097 * <pre> 2098 * StringUtils.substring(null, *, *) = null 2099 * StringUtils.substring("", * , *) = ""; 2100 * StringUtils.substring("abc", 0, 2) = "ab" 2101 * StringUtils.substring("abc", 2, 0) = "" 2102 * StringUtils.substring("abc", 2, 4) = "c" 2103 * StringUtils.substring("abc", 4, 6) = "" 2104 * StringUtils.substring("abc", 2, 2) = "" 2105 * StringUtils.substring("abc", -2, -1) = "b" 2106 * StringUtils.substring("abc", -4, 2) = "ab" 2107 * </pre> 2108 * 2109 * @param str the String to get the substring from, may be null 2110 * @param start the position to start from, negative means 2111 * count back from the end of the String by this many characters 2112 * @param end the position to end at (exclusive), negative means 2113 * count back from the end of the String by this many characters 2114 * @return substring from start position to end position, 2115 * {@code null} if null String input 2116 */ 2117 public static String substring(final String str, int start, int end) { 2118 if (str == null) { 2119 return null; 2120 } 2121 2122 // handle negatives 2123 if (end < 0) { 2124 end = str.length() + end; // remember end is negative 2125 } 2126 if (start < 0) { 2127 start = str.length() + start; // remember start is negative 2128 } 2129 2130 // check length next 2131 if (end > str.length()) { 2132 end = str.length(); 2133 } 2134 2135 // if start is greater than end, return "" 2136 if (start > end) { 2137 return EMPTY; 2138 } 2139 2140 if (start < 0) { 2141 start = 0; 2142 } 2143 if (end < 0) { 2144 end = 0; 2145 } 2146 2147 return str.substring(start, end); 2148 } 2149 2150 // Left/Right/Mid 2151 //----------------------------------------------------------------------- 2152 /** 2153 * <p>Gets the leftmost {@code len} characters of a String.</p> 2154 * 2155 * <p>If {@code len} characters are not available, or the 2156 * String is {@code null}, the String will be returned without 2157 * an exception. An empty String is returned if len is negative.</p> 2158 * 2159 * <pre> 2160 * StringUtils.left(null, *) = null 2161 * StringUtils.left(*, -ve) = "" 2162 * StringUtils.left("", *) = "" 2163 * StringUtils.left("abc", 0) = "" 2164 * StringUtils.left("abc", 2) = "ab" 2165 * StringUtils.left("abc", 4) = "abc" 2166 * </pre> 2167 * 2168 * @param str the String to get the leftmost characters from, may be null 2169 * @param len the length of the required String 2170 * @return the leftmost characters, {@code null} if null String input 2171 */ 2172 public static String left(final String str, final int len) { 2173 if (str == null) { 2174 return null; 2175 } 2176 if (len < 0) { 2177 return EMPTY; 2178 } 2179 if (str.length() <= len) { 2180 return str; 2181 } 2182 return str.substring(0, len); 2183 } 2184 2185 /** 2186 * <p>Gets the rightmost {@code len} characters of a String.</p> 2187 * 2188 * <p>If {@code len} characters are not available, or the String 2189 * is {@code null}, the String will be returned without an 2190 * an exception. An empty String is returned if len is negative.</p> 2191 * 2192 * <pre> 2193 * StringUtils.right(null, *) = null 2194 * StringUtils.right(*, -ve) = "" 2195 * StringUtils.right("", *) = "" 2196 * StringUtils.right("abc", 0) = "" 2197 * StringUtils.right("abc", 2) = "bc" 2198 * StringUtils.right("abc", 4) = "abc" 2199 * </pre> 2200 * 2201 * @param str the String to get the rightmost characters from, may be null 2202 * @param len the length of the required String 2203 * @return the rightmost characters, {@code null} if null String input 2204 */ 2205 public static String right(final String str, final int len) { 2206 if (str == null) { 2207 return null; 2208 } 2209 if (len < 0) { 2210 return EMPTY; 2211 } 2212 if (str.length() <= len) { 2213 return str; 2214 } 2215 return str.substring(str.length() - len); 2216 } 2217 2218 /** 2219 * <p>Gets {@code len} characters from the middle of a String.</p> 2220 * 2221 * <p>If {@code len} characters are not available, the remainder 2222 * of the String will be returned without an exception. If the 2223 * String is {@code null}, {@code null} will be returned. 2224 * An empty String is returned if len is negative or exceeds the 2225 * length of {@code str}.</p> 2226 * 2227 * <pre> 2228 * StringUtils.mid(null, *, *) = null 2229 * StringUtils.mid(*, *, -ve) = "" 2230 * StringUtils.mid("", 0, *) = "" 2231 * StringUtils.mid("abc", 0, 2) = "ab" 2232 * StringUtils.mid("abc", 0, 4) = "abc" 2233 * StringUtils.mid("abc", 2, 4) = "c" 2234 * StringUtils.mid("abc", 4, 2) = "" 2235 * StringUtils.mid("abc", -2, 2) = "ab" 2236 * </pre> 2237 * 2238 * @param str the String to get the characters from, may be null 2239 * @param pos the position to start from, negative treated as zero 2240 * @param len the length of the required String 2241 * @return the middle characters, {@code null} if null String input 2242 */ 2243 public static String mid(final String str, int pos, final int len) { 2244 if (str == null) { 2245 return null; 2246 } 2247 if (len < 0 || pos > str.length()) { 2248 return EMPTY; 2249 } 2250 if (pos < 0) { 2251 pos = 0; 2252 } 2253 if (str.length() <= pos + len) { 2254 return str.substring(pos); 2255 } 2256 return str.substring(pos, pos + len); 2257 } 2258 2259 // SubStringAfter/SubStringBefore 2260 //----------------------------------------------------------------------- 2261 /** 2262 * <p>Gets the substring before the first occurrence of a separator. 2263 * The separator is not returned.</p> 2264 * 2265 * <p>A {@code null} string input will return {@code null}. 2266 * An empty ("") string input will return the empty string. 2267 * A {@code null} separator will return the input string.</p> 2268 * 2269 * <p>If nothing is found, the string input is returned.</p> 2270 * 2271 * <pre> 2272 * StringUtils.substringBefore(null, *) = null 2273 * StringUtils.substringBefore("", *) = "" 2274 * StringUtils.substringBefore("abc", "a") = "" 2275 * StringUtils.substringBefore("abcba", "b") = "a" 2276 * StringUtils.substringBefore("abc", "c") = "ab" 2277 * StringUtils.substringBefore("abc", "d") = "abc" 2278 * StringUtils.substringBefore("abc", "") = "" 2279 * StringUtils.substringBefore("abc", null) = "abc" 2280 * </pre> 2281 * 2282 * @param str the String to get a substring from, may be null 2283 * @param separator the String to search for, may be null 2284 * @return the substring before the first occurrence of the separator, 2285 * {@code null} if null String input 2286 * @since 2.0 2287 */ 2288 public static String substringBefore(final String str, final String separator) { 2289 if (isEmpty(str) || separator == null) { 2290 return str; 2291 } 2292 if (separator.isEmpty()) { 2293 return EMPTY; 2294 } 2295 final int pos = str.indexOf(separator); 2296 if (pos == INDEX_NOT_FOUND) { 2297 return str; 2298 } 2299 return str.substring(0, pos); 2300 } 2301 2302 /** 2303 * <p>Gets the substring after the first occurrence of a separator. 2304 * The separator is not returned.</p> 2305 * 2306 * <p>A {@code null} string input will return {@code null}. 2307 * An empty ("") string input will return the empty string. 2308 * A {@code null} separator will return the empty string if the 2309 * input string is not {@code null}.</p> 2310 * 2311 * <p>If nothing is found, the empty string is returned.</p> 2312 * 2313 * <pre> 2314 * StringUtils.substringAfter(null, *) = null 2315 * StringUtils.substringAfter("", *) = "" 2316 * StringUtils.substringAfter(*, null) = "" 2317 * StringUtils.substringAfter("abc", "a") = "bc" 2318 * StringUtils.substringAfter("abcba", "b") = "cba" 2319 * StringUtils.substringAfter("abc", "c") = "" 2320 * StringUtils.substringAfter("abc", "d") = "" 2321 * StringUtils.substringAfter("abc", "") = "abc" 2322 * </pre> 2323 * 2324 * @param str the String to get a substring from, may be null 2325 * @param separator the String to search for, may be null 2326 * @return the substring after the first occurrence of the separator, 2327 * {@code null} if null String input 2328 * @since 2.0 2329 */ 2330 public static String substringAfter(final String str, final String separator) { 2331 if (isEmpty(str)) { 2332 return str; 2333 } 2334 if (separator == null) { 2335 return EMPTY; 2336 } 2337 final int pos = str.indexOf(separator); 2338 if (pos == INDEX_NOT_FOUND) { 2339 return EMPTY; 2340 } 2341 return str.substring(pos + separator.length()); 2342 } 2343 2344 /** 2345 * <p>Gets the substring before the last occurrence of a separator. 2346 * The separator is not returned.</p> 2347 * 2348 * <p>A {@code null} string input will return {@code null}. 2349 * An empty ("") string input will return the empty string. 2350 * An empty or {@code null} separator will return the input string.</p> 2351 * 2352 * <p>If nothing is found, the string input is returned.</p> 2353 * 2354 * <pre> 2355 * StringUtils.substringBeforeLast(null, *) = null 2356 * StringUtils.substringBeforeLast("", *) = "" 2357 * StringUtils.substringBeforeLast("abcba", "b") = "abc" 2358 * StringUtils.substringBeforeLast("abc", "c") = "ab" 2359 * StringUtils.substringBeforeLast("a", "a") = "" 2360 * StringUtils.substringBeforeLast("a", "z") = "a" 2361 * StringUtils.substringBeforeLast("a", null) = "a" 2362 * StringUtils.substringBeforeLast("a", "") = "a" 2363 * </pre> 2364 * 2365 * @param str the String to get a substring from, may be null 2366 * @param separator the String to search for, may be null 2367 * @return the substring before the last occurrence of the separator, 2368 * {@code null} if null String input 2369 * @since 2.0 2370 */ 2371 public static String substringBeforeLast(final String str, final String separator) { 2372 if (isEmpty(str) || isEmpty(separator)) { 2373 return str; 2374 } 2375 final int pos = str.lastIndexOf(separator); 2376 if (pos == INDEX_NOT_FOUND) { 2377 return str; 2378 } 2379 return str.substring(0, pos); 2380 } 2381 2382 /** 2383 * <p>Gets the substring after the last occurrence of a separator. 2384 * The separator is not returned.</p> 2385 * 2386 * <p>A {@code null} string input will return {@code null}. 2387 * An empty ("") string input will return the empty string. 2388 * An empty or {@code null} separator will return the empty string if 2389 * the input string is not {@code null}.</p> 2390 * 2391 * <p>If nothing is found, the empty string is returned.</p> 2392 * 2393 * <pre> 2394 * StringUtils.substringAfterLast(null, *) = null 2395 * StringUtils.substringAfterLast("", *) = "" 2396 * StringUtils.substringAfterLast(*, "") = "" 2397 * StringUtils.substringAfterLast(*, null) = "" 2398 * StringUtils.substringAfterLast("abc", "a") = "bc" 2399 * StringUtils.substringAfterLast("abcba", "b") = "a" 2400 * StringUtils.substringAfterLast("abc", "c") = "" 2401 * StringUtils.substringAfterLast("a", "a") = "" 2402 * StringUtils.substringAfterLast("a", "z") = "" 2403 * </pre> 2404 * 2405 * @param str the String to get a substring from, may be null 2406 * @param separator the String to search for, may be null 2407 * @return the substring after the last occurrence of the separator, 2408 * {@code null} if null String input 2409 * @since 2.0 2410 */ 2411 public static String substringAfterLast(final String str, final String separator) { 2412 if (isEmpty(str)) { 2413 return str; 2414 } 2415 if (isEmpty(separator)) { 2416 return EMPTY; 2417 } 2418 final int pos = str.lastIndexOf(separator); 2419 if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) { 2420 return EMPTY; 2421 } 2422 return str.substring(pos + separator.length()); 2423 } 2424 2425 // Substring between 2426 //----------------------------------------------------------------------- 2427 /** 2428 * <p>Gets the String that is nested in between two instances of the 2429 * same String.</p> 2430 * 2431 * <p>A {@code null} input String returns {@code null}. 2432 * A {@code null} tag returns {@code null}.</p> 2433 * 2434 * <pre> 2435 * StringUtils.substringBetween(null, *) = null 2436 * StringUtils.substringBetween("", "") = "" 2437 * StringUtils.substringBetween("", "tag") = null 2438 * StringUtils.substringBetween("tagabctag", null) = null 2439 * StringUtils.substringBetween("tagabctag", "") = "" 2440 * StringUtils.substringBetween("tagabctag", "tag") = "abc" 2441 * </pre> 2442 * 2443 * @param str the String containing the substring, may be null 2444 * @param tag the String before and after the substring, may be null 2445 * @return the substring, {@code null} if no match 2446 * @since 2.0 2447 */ 2448 public static String substringBetween(final String str, final String tag) { 2449 return substringBetween(str, tag, tag); 2450 } 2451 2452 /** 2453 * <p>Gets the String that is nested in between two Strings. 2454 * Only the first match is returned.</p> 2455 * 2456 * <p>A {@code null} input String returns {@code null}. 2457 * A {@code null} open/close returns {@code null} (no match). 2458 * An empty ("") open and close returns an empty string.</p> 2459 * 2460 * <pre> 2461 * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b" 2462 * StringUtils.substringBetween(null, *, *) = null 2463 * StringUtils.substringBetween(*, null, *) = null 2464 * StringUtils.substringBetween(*, *, null) = null 2465 * StringUtils.substringBetween("", "", "") = "" 2466 * StringUtils.substringBetween("", "", "]") = null 2467 * StringUtils.substringBetween("", "[", "]") = null 2468 * StringUtils.substringBetween("yabcz", "", "") = "" 2469 * StringUtils.substringBetween("yabcz", "y", "z") = "abc" 2470 * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc" 2471 * </pre> 2472 * 2473 * @param str the String containing the substring, may be null 2474 * @param open the String before the substring, may be null 2475 * @param close the String after the substring, may be null 2476 * @return the substring, {@code null} if no match 2477 * @since 2.0 2478 */ 2479 public static String substringBetween(final String str, final String open, final String close) { 2480 if (str == null || open == null || close == null) { 2481 return null; 2482 } 2483 final int start = str.indexOf(open); 2484 if (start != INDEX_NOT_FOUND) { 2485 final int end = str.indexOf(close, start + open.length()); 2486 if (end != INDEX_NOT_FOUND) { 2487 return str.substring(start + open.length(), end); 2488 } 2489 } 2490 return null; 2491 } 2492 2493 /** 2494 * <p>Searches a String for substrings delimited by a start and end tag, 2495 * returning all matching substrings in an array.</p> 2496 * 2497 * <p>A {@code null} input String returns {@code null}. 2498 * A {@code null} open/close returns {@code null} (no match). 2499 * An empty ("") open/close returns {@code null} (no match).</p> 2500 * 2501 * <pre> 2502 * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"] 2503 * StringUtils.substringsBetween(null, *, *) = null 2504 * StringUtils.substringsBetween(*, null, *) = null 2505 * StringUtils.substringsBetween(*, *, null) = null 2506 * StringUtils.substringsBetween("", "[", "]") = [] 2507 * </pre> 2508 * 2509 * @param str the String containing the substrings, null returns null, empty returns empty 2510 * @param open the String identifying the start of the substring, empty returns null 2511 * @param close the String identifying the end of the substring, empty returns null 2512 * @return a String Array of substrings, or {@code null} if no match 2513 * @since 2.3 2514 */ 2515 public static String[] substringsBetween(final String str, final String open, final String close) { 2516 if (str == null || isEmpty(open) || isEmpty(close)) { 2517 return null; 2518 } 2519 final int strLen = str.length(); 2520 if (strLen == 0) { 2521 return ArrayUtils.EMPTY_STRING_ARRAY; 2522 } 2523 final int closeLen = close.length(); 2524 final int openLen = open.length(); 2525 final List<String> list = new ArrayList<String>(); 2526 int pos = 0; 2527 while (pos < strLen - closeLen) { 2528 int start = str.indexOf(open, pos); 2529 if (start < 0) { 2530 break; 2531 } 2532 start += openLen; 2533 final int end = str.indexOf(close, start); 2534 if (end < 0) { 2535 break; 2536 } 2537 list.add(str.substring(start, end)); 2538 pos = end + closeLen; 2539 } 2540 if (list.isEmpty()) { 2541 return null; 2542 } 2543 return list.toArray(new String [list.size()]); 2544 } 2545 2546 // Nested extraction 2547 //----------------------------------------------------------------------- 2548 2549 // Splitting 2550 //----------------------------------------------------------------------- 2551 /** 2552 * <p>Splits the provided text into an array, using whitespace as the 2553 * separator. 2554 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 2555 * 2556 * <p>The separator is not included in the returned String array. 2557 * Adjacent separators are treated as one separator. 2558 * For more control over the split use the StrTokenizer class.</p> 2559 * 2560 * <p>A {@code null} input String returns {@code null}.</p> 2561 * 2562 * <pre> 2563 * StringUtils.split(null) = null 2564 * StringUtils.split("") = [] 2565 * StringUtils.split("abc def") = ["abc", "def"] 2566 * StringUtils.split("abc def") = ["abc", "def"] 2567 * StringUtils.split(" abc ") = ["abc"] 2568 * </pre> 2569 * 2570 * @param str the String to parse, may be null 2571 * @return an array of parsed Strings, {@code null} if null String input 2572 */ 2573 public static String[] split(final String str) { 2574 return split(str, null, -1); 2575 } 2576 2577 /** 2578 * <p>Splits the provided text into an array, separator specified. 2579 * This is an alternative to using StringTokenizer.</p> 2580 * 2581 * <p>The separator is not included in the returned String array. 2582 * Adjacent separators are treated as one separator. 2583 * For more control over the split use the StrTokenizer class.</p> 2584 * 2585 * <p>A {@code null} input String returns {@code null}.</p> 2586 * 2587 * <pre> 2588 * StringUtils.split(null, *) = null 2589 * StringUtils.split("", *) = [] 2590 * StringUtils.split("a.b.c", '.') = ["a", "b", "c"] 2591 * StringUtils.split("a..b.c", '.') = ["a", "b", "c"] 2592 * StringUtils.split("a:b:c", '.') = ["a:b:c"] 2593 * StringUtils.split("a b c", ' ') = ["a", "b", "c"] 2594 * </pre> 2595 * 2596 * @param str the String to parse, may be null 2597 * @param separatorChar the character used as the delimiter 2598 * @return an array of parsed Strings, {@code null} if null String input 2599 * @since 2.0 2600 */ 2601 public static String[] split(final String str, final char separatorChar) { 2602 return splitWorker(str, separatorChar, false); 2603 } 2604 2605 /** 2606 * <p>Splits the provided text into an array, separators specified. 2607 * This is an alternative to using StringTokenizer.</p> 2608 * 2609 * <p>The separator is not included in the returned String array. 2610 * Adjacent separators are treated as one separator. 2611 * For more control over the split use the StrTokenizer class.</p> 2612 * 2613 * <p>A {@code null} input String returns {@code null}. 2614 * A {@code null} separatorChars splits on whitespace.</p> 2615 * 2616 * <pre> 2617 * StringUtils.split(null, *) = null 2618 * StringUtils.split("", *) = [] 2619 * StringUtils.split("abc def", null) = ["abc", "def"] 2620 * StringUtils.split("abc def", " ") = ["abc", "def"] 2621 * StringUtils.split("abc def", " ") = ["abc", "def"] 2622 * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] 2623 * </pre> 2624 * 2625 * @param str the String to parse, may be null 2626 * @param separatorChars the characters used as the delimiters, 2627 * {@code null} splits on whitespace 2628 * @return an array of parsed Strings, {@code null} if null String input 2629 */ 2630 public static String[] split(final String str, final String separatorChars) { 2631 return splitWorker(str, separatorChars, -1, false); 2632 } 2633 2634 /** 2635 * <p>Splits the provided text into an array with a maximum length, 2636 * separators specified.</p> 2637 * 2638 * <p>The separator is not included in the returned String array. 2639 * Adjacent separators are treated as one separator.</p> 2640 * 2641 * <p>A {@code null} input String returns {@code null}. 2642 * A {@code null} separatorChars splits on whitespace.</p> 2643 * 2644 * <p>If more than {@code max} delimited substrings are found, the last 2645 * returned string includes all characters after the first {@code max - 1} 2646 * returned strings (including separator characters).</p> 2647 * 2648 * <pre> 2649 * StringUtils.split(null, *, *) = null 2650 * StringUtils.split("", *, *) = [] 2651 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 2652 * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"] 2653 * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 2654 * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 2655 * </pre> 2656 * 2657 * @param str the String to parse, may be null 2658 * @param separatorChars the characters used as the delimiters, 2659 * {@code null} splits on whitespace 2660 * @param max the maximum number of elements to include in the 2661 * array. A zero or negative value implies no limit 2662 * @return an array of parsed Strings, {@code null} if null String input 2663 */ 2664 public static String[] split(final String str, final String separatorChars, final int max) { 2665 return splitWorker(str, separatorChars, max, false); 2666 } 2667 2668 /** 2669 * <p>Splits the provided text into an array, separator string specified.</p> 2670 * 2671 * <p>The separator(s) will not be included in the returned String array. 2672 * Adjacent separators are treated as one separator.</p> 2673 * 2674 * <p>A {@code null} input String returns {@code null}. 2675 * A {@code null} separator splits on whitespace.</p> 2676 * 2677 * <pre> 2678 * StringUtils.splitByWholeSeparator(null, *) = null 2679 * StringUtils.splitByWholeSeparator("", *) = [] 2680 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 2681 * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"] 2682 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"] 2683 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 2684 * </pre> 2685 * 2686 * @param str the String to parse, may be null 2687 * @param separator String containing the String to be used as a delimiter, 2688 * {@code null} splits on whitespace 2689 * @return an array of parsed Strings, {@code null} if null String was input 2690 */ 2691 public static String[] splitByWholeSeparator(final String str, final String separator) { 2692 return splitByWholeSeparatorWorker( str, separator, -1, false ) ; 2693 } 2694 2695 /** 2696 * <p>Splits the provided text into an array, separator string specified. 2697 * Returns a maximum of {@code max} substrings.</p> 2698 * 2699 * <p>The separator(s) will not be included in the returned String array. 2700 * Adjacent separators are treated as one separator.</p> 2701 * 2702 * <p>A {@code null} input String returns {@code null}. 2703 * A {@code null} separator splits on whitespace.</p> 2704 * 2705 * <pre> 2706 * StringUtils.splitByWholeSeparator(null, *, *) = null 2707 * StringUtils.splitByWholeSeparator("", *, *) = [] 2708 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 2709 * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"] 2710 * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 2711 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 2712 * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 2713 * </pre> 2714 * 2715 * @param str the String to parse, may be null 2716 * @param separator String containing the String to be used as a delimiter, 2717 * {@code null} splits on whitespace 2718 * @param max the maximum number of elements to include in the returned 2719 * array. A zero or negative value implies no limit. 2720 * @return an array of parsed Strings, {@code null} if null String was input 2721 */ 2722 public static String[] splitByWholeSeparator( final String str, final String separator, final int max ) { 2723 return splitByWholeSeparatorWorker(str, separator, max, false); 2724 } 2725 2726 /** 2727 * <p>Splits the provided text into an array, separator string specified. </p> 2728 * 2729 * <p>The separator is not included in the returned String array. 2730 * Adjacent separators are treated as separators for empty tokens. 2731 * For more control over the split use the StrTokenizer class.</p> 2732 * 2733 * <p>A {@code null} input String returns {@code null}. 2734 * A {@code null} separator splits on whitespace.</p> 2735 * 2736 * <pre> 2737 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null 2738 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = [] 2739 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"] 2740 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"] 2741 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 2742 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"] 2743 * </pre> 2744 * 2745 * @param str the String to parse, may be null 2746 * @param separator String containing the String to be used as a delimiter, 2747 * {@code null} splits on whitespace 2748 * @return an array of parsed Strings, {@code null} if null String was input 2749 * @since 2.4 2750 */ 2751 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) { 2752 return splitByWholeSeparatorWorker(str, separator, -1, true); 2753 } 2754 2755 /** 2756 * <p>Splits the provided text into an array, separator string specified. 2757 * Returns a maximum of {@code max} substrings.</p> 2758 * 2759 * <p>The separator is not included in the returned String array. 2760 * Adjacent separators are treated as separators for empty tokens. 2761 * For more control over the split use the StrTokenizer class.</p> 2762 * 2763 * <p>A {@code null} input String returns {@code null}. 2764 * A {@code null} separator splits on whitespace.</p> 2765 * 2766 * <pre> 2767 * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null 2768 * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = [] 2769 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"] 2770 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"] 2771 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 2772 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"] 2773 * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"] 2774 * </pre> 2775 * 2776 * @param str the String to parse, may be null 2777 * @param separator String containing the String to be used as a delimiter, 2778 * {@code null} splits on whitespace 2779 * @param max the maximum number of elements to include in the returned 2780 * array. A zero or negative value implies no limit. 2781 * @return an array of parsed Strings, {@code null} if null String was input 2782 * @since 2.4 2783 */ 2784 public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) { 2785 return splitByWholeSeparatorWorker(str, separator, max, true); 2786 } 2787 2788 /** 2789 * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods. 2790 * 2791 * @param str the String to parse, may be {@code null} 2792 * @param separator String containing the String to be used as a delimiter, 2793 * {@code null} splits on whitespace 2794 * @param max the maximum number of elements to include in the returned 2795 * array. A zero or negative value implies no limit. 2796 * @param preserveAllTokens if {@code true}, adjacent separators are 2797 * treated as empty token separators; if {@code false}, adjacent 2798 * separators are treated as one separator. 2799 * @return an array of parsed Strings, {@code null} if null String input 2800 * @since 2.4 2801 */ 2802 private static String[] splitByWholeSeparatorWorker( 2803 final String str, final String separator, final int max, final boolean preserveAllTokens) { 2804 if (str == null) { 2805 return null; 2806 } 2807 2808 final int len = str.length(); 2809 2810 if (len == 0) { 2811 return ArrayUtils.EMPTY_STRING_ARRAY; 2812 } 2813 2814 if (separator == null || EMPTY.equals(separator)) { 2815 // Split on whitespace. 2816 return splitWorker(str, null, max, preserveAllTokens); 2817 } 2818 2819 final int separatorLength = separator.length(); 2820 2821 final ArrayList<String> substrings = new ArrayList<String>(); 2822 int numberOfSubstrings = 0; 2823 int beg = 0; 2824 int end = 0; 2825 while (end < len) { 2826 end = str.indexOf(separator, beg); 2827 2828 if (end > -1) { 2829 if (end > beg) { 2830 numberOfSubstrings += 1; 2831 2832 if (numberOfSubstrings == max) { 2833 end = len; 2834 substrings.add(str.substring(beg)); 2835 } else { 2836 // The following is OK, because String.substring( beg, end ) excludes 2837 // the character at the position 'end'. 2838 substrings.add(str.substring(beg, end)); 2839 2840 // Set the starting point for the next search. 2841 // The following is equivalent to beg = end + (separatorLength - 1) + 1, 2842 // which is the right calculation: 2843 beg = end + separatorLength; 2844 } 2845 } else { 2846 // We found a consecutive occurrence of the separator, so skip it. 2847 if (preserveAllTokens) { 2848 numberOfSubstrings += 1; 2849 if (numberOfSubstrings == max) { 2850 end = len; 2851 substrings.add(str.substring(beg)); 2852 } else { 2853 substrings.add(EMPTY); 2854 } 2855 } 2856 beg = end + separatorLength; 2857 } 2858 } else { 2859 // String.substring( beg ) goes from 'beg' to the end of the String. 2860 substrings.add(str.substring(beg)); 2861 end = len; 2862 } 2863 } 2864 2865 return substrings.toArray(new String[substrings.size()]); 2866 } 2867 2868 // ----------------------------------------------------------------------- 2869 /** 2870 * <p>Splits the provided text into an array, using whitespace as the 2871 * separator, preserving all tokens, including empty tokens created by 2872 * adjacent separators. This is an alternative to using StringTokenizer. 2873 * Whitespace is defined by {@link Character#isWhitespace(char)}.</p> 2874 * 2875 * <p>The separator is not included in the returned String array. 2876 * Adjacent separators are treated as separators for empty tokens. 2877 * For more control over the split use the StrTokenizer class.</p> 2878 * 2879 * <p>A {@code null} input String returns {@code null}.</p> 2880 * 2881 * <pre> 2882 * StringUtils.splitPreserveAllTokens(null) = null 2883 * StringUtils.splitPreserveAllTokens("") = [] 2884 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"] 2885 * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"] 2886 * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""] 2887 * </pre> 2888 * 2889 * @param str the String to parse, may be {@code null} 2890 * @return an array of parsed Strings, {@code null} if null String input 2891 * @since 2.1 2892 */ 2893 public static String[] splitPreserveAllTokens(final String str) { 2894 return splitWorker(str, null, -1, true); 2895 } 2896 2897 /** 2898 * <p>Splits the provided text into an array, separator specified, 2899 * preserving all tokens, including empty tokens created by adjacent 2900 * separators. This is an alternative to using StringTokenizer.</p> 2901 * 2902 * <p>The separator is not included in the returned String array. 2903 * Adjacent separators are treated as separators for empty tokens. 2904 * For more control over the split use the StrTokenizer class.</p> 2905 * 2906 * <p>A {@code null} input String returns {@code null}.</p> 2907 * 2908 * <pre> 2909 * StringUtils.splitPreserveAllTokens(null, *) = null 2910 * StringUtils.splitPreserveAllTokens("", *) = [] 2911 * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"] 2912 * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"] 2913 * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"] 2914 * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"] 2915 * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"] 2916 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""] 2917 * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""] 2918 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", a", "b", "c"] 2919 * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", a", "b", "c"] 2920 * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", a", "b", "c", ""] 2921 * </pre> 2922 * 2923 * @param str the String to parse, may be {@code null} 2924 * @param separatorChar the character used as the delimiter, 2925 * {@code null} splits on whitespace 2926 * @return an array of parsed Strings, {@code null} if null String input 2927 * @since 2.1 2928 */ 2929 public static String[] splitPreserveAllTokens(final String str, final char separatorChar) { 2930 return splitWorker(str, separatorChar, true); 2931 } 2932 2933 /** 2934 * Performs the logic for the {@code split} and 2935 * {@code splitPreserveAllTokens} methods that do not return a 2936 * maximum array length. 2937 * 2938 * @param str the String to parse, may be {@code null} 2939 * @param separatorChar the separate character 2940 * @param preserveAllTokens if {@code true}, adjacent separators are 2941 * treated as empty token separators; if {@code false}, adjacent 2942 * separators are treated as one separator. 2943 * @return an array of parsed Strings, {@code null} if null String input 2944 */ 2945 private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) { 2946 // Performance tuned for 2.0 (JDK1.4) 2947 2948 if (str == null) { 2949 return null; 2950 } 2951 final int len = str.length(); 2952 if (len == 0) { 2953 return ArrayUtils.EMPTY_STRING_ARRAY; 2954 } 2955 final List<String> list = new ArrayList<String>(); 2956 int i = 0, start = 0; 2957 boolean match = false; 2958 boolean lastMatch = false; 2959 while (i < len) { 2960 if (str.charAt(i) == separatorChar) { 2961 if (match || preserveAllTokens) { 2962 list.add(str.substring(start, i)); 2963 match = false; 2964 lastMatch = true; 2965 } 2966 start = ++i; 2967 continue; 2968 } 2969 lastMatch = false; 2970 match = true; 2971 i++; 2972 } 2973 if (match || preserveAllTokens && lastMatch) { 2974 list.add(str.substring(start, i)); 2975 } 2976 return list.toArray(new String[list.size()]); 2977 } 2978 2979 /** 2980 * <p>Splits the provided text into an array, separators specified, 2981 * preserving all tokens, including empty tokens created by adjacent 2982 * separators. This is an alternative to using StringTokenizer.</p> 2983 * 2984 * <p>The separator is not included in the returned String array. 2985 * Adjacent separators are treated as separators for empty tokens. 2986 * For more control over the split use the StrTokenizer class.</p> 2987 * 2988 * <p>A {@code null} input String returns {@code null}. 2989 * A {@code null} separatorChars splits on whitespace.</p> 2990 * 2991 * <pre> 2992 * StringUtils.splitPreserveAllTokens(null, *) = null 2993 * StringUtils.splitPreserveAllTokens("", *) = [] 2994 * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"] 2995 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"] 2996 * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", def"] 2997 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"] 2998 * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""] 2999 * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""] 3000 * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", cd", "ef"] 3001 * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", cd", "ef"] 3002 * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", cd", "ef"] 3003 * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", cd", "ef", ""] 3004 * </pre> 3005 * 3006 * @param str the String to parse, may be {@code null} 3007 * @param separatorChars the characters used as the delimiters, 3008 * {@code null} splits on whitespace 3009 * @return an array of parsed Strings, {@code null} if null String input 3010 * @since 2.1 3011 */ 3012 public static String[] splitPreserveAllTokens(final String str, final String separatorChars) { 3013 return splitWorker(str, separatorChars, -1, true); 3014 } 3015 3016 /** 3017 * <p>Splits the provided text into an array with a maximum length, 3018 * separators specified, preserving all tokens, including empty tokens 3019 * created by adjacent separators.</p> 3020 * 3021 * <p>The separator is not included in the returned String array. 3022 * Adjacent separators are treated as separators for empty tokens. 3023 * Adjacent separators are treated as one separator.</p> 3024 * 3025 * <p>A {@code null} input String returns {@code null}. 3026 * A {@code null} separatorChars splits on whitespace.</p> 3027 * 3028 * <p>If more than {@code max} delimited substrings are found, the last 3029 * returned string includes all characters after the first {@code max - 1} 3030 * returned strings (including separator characters).</p> 3031 * 3032 * <pre> 3033 * StringUtils.splitPreserveAllTokens(null, *, *) = null 3034 * StringUtils.splitPreserveAllTokens("", *, *) = [] 3035 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "cd", "ef"] 3036 * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "cd", "ef"] 3037 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] 3038 * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] 3039 * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"] 3040 * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"] 3041 * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"] 3042 * </pre> 3043 * 3044 * @param str the String to parse, may be {@code null} 3045 * @param separatorChars the characters used as the delimiters, 3046 * {@code null} splits on whitespace 3047 * @param max the maximum number of elements to include in the 3048 * array. A zero or negative value implies no limit 3049 * @return an array of parsed Strings, {@code null} if null String input 3050 * @since 2.1 3051 */ 3052 public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) { 3053 return splitWorker(str, separatorChars, max, true); 3054 } 3055 3056 /** 3057 * Performs the logic for the {@code split} and 3058 * {@code splitPreserveAllTokens} methods that return a maximum array 3059 * length. 3060 * 3061 * @param str the String to parse, may be {@code null} 3062 * @param separatorChars the separate character 3063 * @param max the maximum number of elements to include in the 3064 * array. A zero or negative value implies no limit. 3065 * @param preserveAllTokens if {@code true}, adjacent separators are 3066 * treated as empty token separators; if {@code false}, adjacent 3067 * separators are treated as one separator. 3068 * @return an array of parsed Strings, {@code null} if null String input 3069 */ 3070 private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) { 3071 // Performance tuned for 2.0 (JDK1.4) 3072 // Direct code is quicker than StringTokenizer. 3073 // Also, StringTokenizer uses isSpace() not isWhitespace() 3074 3075 if (str == null) { 3076 return null; 3077 } 3078 final int len = str.length(); 3079 if (len == 0) { 3080 return ArrayUtils.EMPTY_STRING_ARRAY; 3081 } 3082 final List<String> list = new ArrayList<String>(); 3083 int sizePlus1 = 1; 3084 int i = 0, start = 0; 3085 boolean match = false; 3086 boolean lastMatch = false; 3087 if (separatorChars == null) { 3088 // Null separator means use whitespace 3089 while (i < len) { 3090 if (Character.isWhitespace(str.charAt(i))) { 3091 if (match || preserveAllTokens) { 3092 lastMatch = true; 3093 if (sizePlus1++ == max) { 3094 i = len; 3095 lastMatch = false; 3096 } 3097 list.add(str.substring(start, i)); 3098 match = false; 3099 } 3100 start = ++i; 3101 continue; 3102 } 3103 lastMatch = false; 3104 match = true; 3105 i++; 3106 } 3107 } else if (separatorChars.length() == 1) { 3108 // Optimise 1 character case 3109 final char sep = separatorChars.charAt(0); 3110 while (i < len) { 3111 if (str.charAt(i) == sep) { 3112 if (match || preserveAllTokens) { 3113 lastMatch = true; 3114 if (sizePlus1++ == max) { 3115 i = len; 3116 lastMatch = false; 3117 } 3118 list.add(str.substring(start, i)); 3119 match = false; 3120 } 3121 start = ++i; 3122 continue; 3123 } 3124 lastMatch = false; 3125 match = true; 3126 i++; 3127 } 3128 } else { 3129 // standard case 3130 while (i < len) { 3131 if (separatorChars.indexOf(str.charAt(i)) >= 0) { 3132 if (match || preserveAllTokens) { 3133 lastMatch = true; 3134 if (sizePlus1++ == max) { 3135 i = len; 3136 lastMatch = false; 3137 } 3138 list.add(str.substring(start, i)); 3139 match = false; 3140 } 3141 start = ++i; 3142 continue; 3143 } 3144 lastMatch = false; 3145 match = true; 3146 i++; 3147 } 3148 } 3149 if (match || preserveAllTokens && lastMatch) { 3150 list.add(str.substring(start, i)); 3151 } 3152 return list.toArray(new String[list.size()]); 3153 } 3154 3155 /** 3156 * <p>Splits a String by Character type as returned by 3157 * {@code java.lang.Character.getType(char)}. Groups of contiguous 3158 * characters of the same type are returned as complete tokens. 3159 * <pre> 3160 * StringUtils.splitByCharacterType(null) = null 3161 * StringUtils.splitByCharacterType("") = [] 3162 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 3163 * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"] 3164 * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 3165 * StringUtils.splitByCharacterType("number5") = ["number", "5"] 3166 * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"] 3167 * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"] 3168 * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"] 3169 * </pre> 3170 * @param str the String to split, may be {@code null} 3171 * @return an array of parsed Strings, {@code null} if null String input 3172 * @since 2.4 3173 */ 3174 public static String[] splitByCharacterType(final String str) { 3175 return splitByCharacterType(str, false); 3176 } 3177 3178 /** 3179 * <p>Splits a String by Character type as returned by 3180 * {@code java.lang.Character.getType(char)}. Groups of contiguous 3181 * characters of the same type are returned as complete tokens, with the 3182 * following exception: the character of type 3183 * {@code Character.UPPERCASE_LETTER}, if any, immediately 3184 * preceding a token of type {@code Character.LOWERCASE_LETTER} 3185 * will belong to the following token rather than to the preceding, if any, 3186 * {@code Character.UPPERCASE_LETTER} token. 3187 * <pre> 3188 * StringUtils.splitByCharacterTypeCamelCase(null) = null 3189 * StringUtils.splitByCharacterTypeCamelCase("") = [] 3190 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 3191 * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] 3192 * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] 3193 * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"] 3194 * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"] 3195 * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"] 3196 * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"] 3197 * </pre> 3198 * @param str the String to split, may be {@code null} 3199 * @return an array of parsed Strings, {@code null} if null String input 3200 * @since 2.4 3201 */ 3202 public static String[] splitByCharacterTypeCamelCase(final String str) { 3203 return splitByCharacterType(str, true); 3204 } 3205 3206 /** 3207 * <p>Splits a String by Character type as returned by 3208 * {@code java.lang.Character.getType(char)}. Groups of contiguous 3209 * characters of the same type are returned as complete tokens, with the 3210 * following exception: if {@code camelCase} is {@code true}, 3211 * the character of type {@code Character.UPPERCASE_LETTER}, if any, 3212 * immediately preceding a token of type {@code Character.LOWERCASE_LETTER} 3213 * will belong to the following token rather than to the preceding, if any, 3214 * {@code Character.UPPERCASE_LETTER} token. 3215 * @param str the String to split, may be {@code null} 3216 * @param camelCase whether to use so-called "camel-case" for letter types 3217 * @return an array of parsed Strings, {@code null} if null String input 3218 * @since 2.4 3219 */ 3220 private static String[] splitByCharacterType(final String str, final boolean camelCase) { 3221 if (str == null) { 3222 return null; 3223 } 3224 if (str.isEmpty()) { 3225 return ArrayUtils.EMPTY_STRING_ARRAY; 3226 } 3227 final char[] c = str.toCharArray(); 3228 final List<String> list = new ArrayList<String>(); 3229 int tokenStart = 0; 3230 int currentType = Character.getType(c[tokenStart]); 3231 for (int pos = tokenStart + 1; pos < c.length; pos++) { 3232 final int type = Character.getType(c[pos]); 3233 if (type == currentType) { 3234 continue; 3235 } 3236 if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) { 3237 final int newTokenStart = pos - 1; 3238 if (newTokenStart != tokenStart) { 3239 list.add(new String(c, tokenStart, newTokenStart - tokenStart)); 3240 tokenStart = newTokenStart; 3241 } 3242 } else { 3243 list.add(new String(c, tokenStart, pos - tokenStart)); 3244 tokenStart = pos; 3245 } 3246 currentType = type; 3247 } 3248 list.add(new String(c, tokenStart, c.length - tokenStart)); 3249 return list.toArray(new String[list.size()]); 3250 } 3251 3252 // Joining 3253 //----------------------------------------------------------------------- 3254 /** 3255 * <p>Joins the elements of the provided array into a single String 3256 * containing the provided list of elements.</p> 3257 * 3258 * <p>No separator is added to the joined String. 3259 * Null objects or empty strings within the array are represented by 3260 * empty strings.</p> 3261 * 3262 * <pre> 3263 * StringUtils.join(null) = null 3264 * StringUtils.join([]) = "" 3265 * StringUtils.join([null]) = "" 3266 * StringUtils.join(["a", "b", "c"]) = "abc" 3267 * StringUtils.join([null, "", "a"]) = "a" 3268 * </pre> 3269 * 3270 * @param <T> the specific type of values to join together 3271 * @param elements the values to join together, may be null 3272 * @return the joined String, {@code null} if null array input 3273 * @since 2.0 3274 * @since 3.0 Changed signature to use varargs 3275 */ 3276 public static <T> String join(final T... elements) { 3277 return join(elements, null); 3278 } 3279 3280 /** 3281 * <p>Joins the elements of the provided array into a single String 3282 * containing the provided list of elements.</p> 3283 * 3284 * <p>No delimiter is added before or after the list. 3285 * Null objects or empty strings within the array are represented by 3286 * empty strings.</p> 3287 * 3288 * <pre> 3289 * StringUtils.join(null, *) = null 3290 * StringUtils.join([], *) = "" 3291 * StringUtils.join([null], *) = "" 3292 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 3293 * StringUtils.join(["a", "b", "c"], null) = "abc" 3294 * StringUtils.join([null, "", "a"], ';') = ";;a" 3295 * </pre> 3296 * 3297 * @param array the array of values to join together, may be null 3298 * @param separator the separator character to use 3299 * @return the joined String, {@code null} if null array input 3300 * @since 2.0 3301 */ 3302 public static String join(final Object[] array, final char separator) { 3303 if (array == null) { 3304 return null; 3305 } 3306 return join(array, separator, 0, array.length); 3307 } 3308 3309 /** 3310 * <p> 3311 * Joins the elements of the provided array into a single String containing the provided list of elements. 3312 * </p> 3313 * 3314 * <p> 3315 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3316 * by empty strings. 3317 * </p> 3318 * 3319 * <pre> 3320 * StringUtils.join(null, *) = null 3321 * StringUtils.join([], *) = "" 3322 * StringUtils.join([null], *) = "" 3323 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3324 * StringUtils.join([1, 2, 3], null) = "123" 3325 * </pre> 3326 * 3327 * @param array 3328 * the array of values to join together, may be null 3329 * @param separator 3330 * the separator character to use 3331 * @return the joined String, {@code null} if null array input 3332 * @since 3.2 3333 */ 3334 public static String join(final long[] array, final char separator) { 3335 if (array == null) { 3336 return null; 3337 } 3338 return join(array, separator, 0, array.length); 3339 } 3340 3341 /** 3342 * <p> 3343 * Joins the elements of the provided array into a single String containing the provided list of elements. 3344 * </p> 3345 * 3346 * <p> 3347 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3348 * by empty strings. 3349 * </p> 3350 * 3351 * <pre> 3352 * StringUtils.join(null, *) = null 3353 * StringUtils.join([], *) = "" 3354 * StringUtils.join([null], *) = "" 3355 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3356 * StringUtils.join([1, 2, 3], null) = "123" 3357 * </pre> 3358 * 3359 * @param array 3360 * the array of values to join together, may be null 3361 * @param separator 3362 * the separator character to use 3363 * @return the joined String, {@code null} if null array input 3364 * @since 3.2 3365 */ 3366 public static String join(final int[] array, final char separator) { 3367 if (array == null) { 3368 return null; 3369 } 3370 return join(array, separator, 0, array.length); 3371 } 3372 3373 /** 3374 * <p> 3375 * Joins the elements of the provided array into a single String containing the provided list of elements. 3376 * </p> 3377 * 3378 * <p> 3379 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3380 * by empty strings. 3381 * </p> 3382 * 3383 * <pre> 3384 * StringUtils.join(null, *) = null 3385 * StringUtils.join([], *) = "" 3386 * StringUtils.join([null], *) = "" 3387 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3388 * StringUtils.join([1, 2, 3], null) = "123" 3389 * </pre> 3390 * 3391 * @param array 3392 * the array of values to join together, may be null 3393 * @param separator 3394 * the separator character to use 3395 * @return the joined String, {@code null} if null array input 3396 * @since 3.2 3397 */ 3398 public static String join(final short[] array, final char separator) { 3399 if (array == null) { 3400 return null; 3401 } 3402 return join(array, separator, 0, array.length); 3403 } 3404 3405 /** 3406 * <p> 3407 * Joins the elements of the provided array into a single String containing the provided list of elements. 3408 * </p> 3409 * 3410 * <p> 3411 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3412 * by empty strings. 3413 * </p> 3414 * 3415 * <pre> 3416 * StringUtils.join(null, *) = null 3417 * StringUtils.join([], *) = "" 3418 * StringUtils.join([null], *) = "" 3419 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3420 * StringUtils.join([1, 2, 3], null) = "123" 3421 * </pre> 3422 * 3423 * @param array 3424 * the array of values to join together, may be null 3425 * @param separator 3426 * the separator character to use 3427 * @return the joined String, {@code null} if null array input 3428 * @since 3.2 3429 */ 3430 public static String join(final byte[] array, final char separator) { 3431 if (array == null) { 3432 return null; 3433 } 3434 return join(array, separator, 0, array.length); 3435 } 3436 3437 /** 3438 * <p> 3439 * Joins the elements of the provided array into a single String containing the provided list of elements. 3440 * </p> 3441 * 3442 * <p> 3443 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3444 * by empty strings. 3445 * </p> 3446 * 3447 * <pre> 3448 * StringUtils.join(null, *) = null 3449 * StringUtils.join([], *) = "" 3450 * StringUtils.join([null], *) = "" 3451 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3452 * StringUtils.join([1, 2, 3], null) = "123" 3453 * </pre> 3454 * 3455 * @param array 3456 * the array of values to join together, may be null 3457 * @param separator 3458 * the separator character to use 3459 * @return the joined String, {@code null} if null array input 3460 * @since 3.2 3461 */ 3462 public static String join(final char[] array, final char separator) { 3463 if (array == null) { 3464 return null; 3465 } 3466 return join(array, separator, 0, array.length); 3467 } 3468 3469 /** 3470 * <p> 3471 * Joins the elements of the provided array into a single String containing the provided list of elements. 3472 * </p> 3473 * 3474 * <p> 3475 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3476 * by empty strings. 3477 * </p> 3478 * 3479 * <pre> 3480 * StringUtils.join(null, *) = null 3481 * StringUtils.join([], *) = "" 3482 * StringUtils.join([null], *) = "" 3483 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3484 * StringUtils.join([1, 2, 3], null) = "123" 3485 * </pre> 3486 * 3487 * @param array 3488 * the array of values to join together, may be null 3489 * @param separator 3490 * the separator character to use 3491 * @return the joined String, {@code null} if null array input 3492 * @since 3.2 3493 */ 3494 public static String join(final float[] array, final char separator) { 3495 if (array == null) { 3496 return null; 3497 } 3498 return join(array, separator, 0, array.length); 3499 } 3500 3501 /** 3502 * <p> 3503 * Joins the elements of the provided array into a single String containing the provided list of elements. 3504 * </p> 3505 * 3506 * <p> 3507 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3508 * by empty strings. 3509 * </p> 3510 * 3511 * <pre> 3512 * StringUtils.join(null, *) = null 3513 * StringUtils.join([], *) = "" 3514 * StringUtils.join([null], *) = "" 3515 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3516 * StringUtils.join([1, 2, 3], null) = "123" 3517 * </pre> 3518 * 3519 * @param array 3520 * the array of values to join together, may be null 3521 * @param separator 3522 * the separator character to use 3523 * @return the joined String, {@code null} if null array input 3524 * @since 3.2 3525 */ 3526 public static String join(final double[] array, final char separator) { 3527 if (array == null) { 3528 return null; 3529 } 3530 return join(array, separator, 0, array.length); 3531 } 3532 3533 3534 /** 3535 * <p>Joins the elements of the provided array into a single String 3536 * containing the provided list of elements.</p> 3537 * 3538 * <p>No delimiter is added before or after the list. 3539 * Null objects or empty strings within the array are represented by 3540 * empty strings.</p> 3541 * 3542 * <pre> 3543 * StringUtils.join(null, *) = null 3544 * StringUtils.join([], *) = "" 3545 * StringUtils.join([null], *) = "" 3546 * StringUtils.join(["a", "b", "c"], ';') = "a;b;c" 3547 * StringUtils.join(["a", "b", "c"], null) = "abc" 3548 * StringUtils.join([null, "", "a"], ';') = ";;a" 3549 * </pre> 3550 * 3551 * @param array the array of values to join together, may be null 3552 * @param separator the separator character to use 3553 * @param startIndex the first index to start joining from. It is 3554 * an error to pass in an end index past the end of the array 3555 * @param endIndex the index to stop joining from (exclusive). It is 3556 * an error to pass in an end index past the end of the array 3557 * @return the joined String, {@code null} if null array input 3558 * @since 2.0 3559 */ 3560 public static String join(final Object[] array, final char separator, final int startIndex, final int endIndex) { 3561 if (array == null) { 3562 return null; 3563 } 3564 final int noOfItems = endIndex - startIndex; 3565 if (noOfItems <= 0) { 3566 return EMPTY; 3567 } 3568 final StringBuilder buf = new StringBuilder(noOfItems * 16); 3569 for (int i = startIndex; i < endIndex; i++) { 3570 if (i > startIndex) { 3571 buf.append(separator); 3572 } 3573 if (array[i] != null) { 3574 buf.append(array[i]); 3575 } 3576 } 3577 return buf.toString(); 3578 } 3579 3580 /** 3581 * <p> 3582 * Joins the elements of the provided array into a single String containing the provided list of elements. 3583 * </p> 3584 * 3585 * <p> 3586 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3587 * by empty strings. 3588 * </p> 3589 * 3590 * <pre> 3591 * StringUtils.join(null, *) = null 3592 * StringUtils.join([], *) = "" 3593 * StringUtils.join([null], *) = "" 3594 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3595 * StringUtils.join([1, 2, 3], null) = "123" 3596 * </pre> 3597 * 3598 * @param array 3599 * the array of values to join together, may be null 3600 * @param separator 3601 * the separator character to use 3602 * @param startIndex 3603 * the first index to start joining from. It is an error to pass in an end index past the end of the 3604 * array 3605 * @param endIndex 3606 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3607 * the array 3608 * @return the joined String, {@code null} if null array input 3609 * @since 3.2 3610 */ 3611 public static String join(final long[] array, final char separator, final int startIndex, final int endIndex) { 3612 if (array == null) { 3613 return null; 3614 } 3615 final int noOfItems = endIndex - startIndex; 3616 if (noOfItems <= 0) { 3617 return EMPTY; 3618 } 3619 final StringBuilder buf = new StringBuilder(noOfItems * 16); 3620 for (int i = startIndex; i < endIndex; i++) { 3621 if (i > startIndex) { 3622 buf.append(separator); 3623 } 3624 buf.append(array[i]); 3625 } 3626 return buf.toString(); 3627 } 3628 3629 /** 3630 * <p> 3631 * Joins the elements of the provided array into a single String containing the provided list of elements. 3632 * </p> 3633 * 3634 * <p> 3635 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3636 * by empty strings. 3637 * </p> 3638 * 3639 * <pre> 3640 * StringUtils.join(null, *) = null 3641 * StringUtils.join([], *) = "" 3642 * StringUtils.join([null], *) = "" 3643 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3644 * StringUtils.join([1, 2, 3], null) = "123" 3645 * </pre> 3646 * 3647 * @param array 3648 * the array of values to join together, may be null 3649 * @param separator 3650 * the separator character to use 3651 * @param startIndex 3652 * the first index to start joining from. It is an error to pass in an end index past the end of the 3653 * array 3654 * @param endIndex 3655 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3656 * the array 3657 * @return the joined String, {@code null} if null array input 3658 * @since 3.2 3659 */ 3660 public static String join(final int[] array, final char separator, final int startIndex, final int endIndex) { 3661 if (array == null) { 3662 return null; 3663 } 3664 final int noOfItems = endIndex - startIndex; 3665 if (noOfItems <= 0) { 3666 return EMPTY; 3667 } 3668 final StringBuilder buf = new StringBuilder(noOfItems * 16); 3669 for (int i = startIndex; i < endIndex; i++) { 3670 if (i > startIndex) { 3671 buf.append(separator); 3672 } 3673 buf.append(array[i]); 3674 } 3675 return buf.toString(); 3676 } 3677 3678 /** 3679 * <p> 3680 * Joins the elements of the provided array into a single String containing the provided list of elements. 3681 * </p> 3682 * 3683 * <p> 3684 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3685 * by empty strings. 3686 * </p> 3687 * 3688 * <pre> 3689 * StringUtils.join(null, *) = null 3690 * StringUtils.join([], *) = "" 3691 * StringUtils.join([null], *) = "" 3692 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3693 * StringUtils.join([1, 2, 3], null) = "123" 3694 * </pre> 3695 * 3696 * @param array 3697 * the array of values to join together, may be null 3698 * @param separator 3699 * the separator character to use 3700 * @param startIndex 3701 * the first index to start joining from. It is an error to pass in an end index past the end of the 3702 * array 3703 * @param endIndex 3704 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3705 * the array 3706 * @return the joined String, {@code null} if null array input 3707 * @since 3.2 3708 */ 3709 public static String join(final byte[] array, final char separator, final int startIndex, final int endIndex) { 3710 if (array == null) { 3711 return null; 3712 } 3713 final int noOfItems = endIndex - startIndex; 3714 if (noOfItems <= 0) { 3715 return EMPTY; 3716 } 3717 final StringBuilder buf = new StringBuilder(noOfItems * 16); 3718 for (int i = startIndex; i < endIndex; i++) { 3719 if (i > startIndex) { 3720 buf.append(separator); 3721 } 3722 buf.append(array[i]); 3723 } 3724 return buf.toString(); 3725 } 3726 3727 /** 3728 * <p> 3729 * Joins the elements of the provided array into a single String containing the provided list of elements. 3730 * </p> 3731 * 3732 * <p> 3733 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3734 * by empty strings. 3735 * </p> 3736 * 3737 * <pre> 3738 * StringUtils.join(null, *) = null 3739 * StringUtils.join([], *) = "" 3740 * StringUtils.join([null], *) = "" 3741 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3742 * StringUtils.join([1, 2, 3], null) = "123" 3743 * </pre> 3744 * 3745 * @param array 3746 * the array of values to join together, may be null 3747 * @param separator 3748 * the separator character to use 3749 * @param startIndex 3750 * the first index to start joining from. It is an error to pass in an end index past the end of the 3751 * array 3752 * @param endIndex 3753 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3754 * the array 3755 * @return the joined String, {@code null} if null array input 3756 * @since 3.2 3757 */ 3758 public static String join(final short[] array, final char separator, final int startIndex, final int endIndex) { 3759 if (array == null) { 3760 return null; 3761 } 3762 final int noOfItems = endIndex - startIndex; 3763 if (noOfItems <= 0) { 3764 return EMPTY; 3765 } 3766 final StringBuilder buf = new StringBuilder(noOfItems * 16); 3767 for (int i = startIndex; i < endIndex; i++) { 3768 if (i > startIndex) { 3769 buf.append(separator); 3770 } 3771 buf.append(array[i]); 3772 } 3773 return buf.toString(); 3774 } 3775 3776 /** 3777 * <p> 3778 * Joins the elements of the provided array into a single String containing the provided list of elements. 3779 * </p> 3780 * 3781 * <p> 3782 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3783 * by empty strings. 3784 * </p> 3785 * 3786 * <pre> 3787 * StringUtils.join(null, *) = null 3788 * StringUtils.join([], *) = "" 3789 * StringUtils.join([null], *) = "" 3790 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3791 * StringUtils.join([1, 2, 3], null) = "123" 3792 * </pre> 3793 * 3794 * @param array 3795 * the array of values to join together, may be null 3796 * @param separator 3797 * the separator character to use 3798 * @param startIndex 3799 * the first index to start joining from. It is an error to pass in an end index past the end of the 3800 * array 3801 * @param endIndex 3802 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3803 * the array 3804 * @return the joined String, {@code null} if null array input 3805 * @since 3.2 3806 */ 3807 public static String join(final char[] array, final char separator, final int startIndex, final int endIndex) { 3808 if (array == null) { 3809 return null; 3810 } 3811 final int noOfItems = endIndex - startIndex; 3812 if (noOfItems <= 0) { 3813 return EMPTY; 3814 } 3815 final StringBuilder buf = new StringBuilder(noOfItems * 16); 3816 for (int i = startIndex; i < endIndex; i++) { 3817 if (i > startIndex) { 3818 buf.append(separator); 3819 } 3820 buf.append(array[i]); 3821 } 3822 return buf.toString(); 3823 } 3824 3825 /** 3826 * <p> 3827 * Joins the elements of the provided array into a single String containing the provided list of elements. 3828 * </p> 3829 * 3830 * <p> 3831 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3832 * by empty strings. 3833 * </p> 3834 * 3835 * <pre> 3836 * StringUtils.join(null, *) = null 3837 * StringUtils.join([], *) = "" 3838 * StringUtils.join([null], *) = "" 3839 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3840 * StringUtils.join([1, 2, 3], null) = "123" 3841 * </pre> 3842 * 3843 * @param array 3844 * the array of values to join together, may be null 3845 * @param separator 3846 * the separator character to use 3847 * @param startIndex 3848 * the first index to start joining from. It is an error to pass in an end index past the end of the 3849 * array 3850 * @param endIndex 3851 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3852 * the array 3853 * @return the joined String, {@code null} if null array input 3854 * @since 3.2 3855 */ 3856 public static String join(final double[] array, final char separator, final int startIndex, final int endIndex) { 3857 if (array == null) { 3858 return null; 3859 } 3860 final int noOfItems = endIndex - startIndex; 3861 if (noOfItems <= 0) { 3862 return EMPTY; 3863 } 3864 final StringBuilder buf = new StringBuilder(noOfItems * 16); 3865 for (int i = startIndex; i < endIndex; i++) { 3866 if (i > startIndex) { 3867 buf.append(separator); 3868 } 3869 buf.append(array[i]); 3870 } 3871 return buf.toString(); 3872 } 3873 3874 /** 3875 * <p> 3876 * Joins the elements of the provided array into a single String containing the provided list of elements. 3877 * </p> 3878 * 3879 * <p> 3880 * No delimiter is added before or after the list. Null objects or empty strings within the array are represented 3881 * by empty strings. 3882 * </p> 3883 * 3884 * <pre> 3885 * StringUtils.join(null, *) = null 3886 * StringUtils.join([], *) = "" 3887 * StringUtils.join([null], *) = "" 3888 * StringUtils.join([1, 2, 3], ';') = "1;2;3" 3889 * StringUtils.join([1, 2, 3], null) = "123" 3890 * </pre> 3891 * 3892 * @param array 3893 * the array of values to join together, may be null 3894 * @param separator 3895 * the separator character to use 3896 * @param startIndex 3897 * the first index to start joining from. It is an error to pass in an end index past the end of the 3898 * array 3899 * @param endIndex 3900 * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of 3901 * the array 3902 * @return the joined String, {@code null} if null array input 3903 * @since 3.2 3904 */ 3905 public static String join(final float[] array, final char separator, final int startIndex, final int endIndex) { 3906 if (array == null) { 3907 return null; 3908 } 3909 final int noOfItems = endIndex - startIndex; 3910 if (noOfItems <= 0) { 3911 return EMPTY; 3912 } 3913 final StringBuilder buf = new StringBuilder(noOfItems * 16); 3914 for (int i = startIndex; i < endIndex; i++) { 3915 if (i > startIndex) { 3916 buf.append(separator); 3917 } 3918 buf.append(array[i]); 3919 } 3920 return buf.toString(); 3921 } 3922 3923 3924 /** 3925 * <p>Joins the elements of the provided array into a single String 3926 * containing the provided list of elements.</p> 3927 * 3928 * <p>No delimiter is added before or after the list. 3929 * A {@code null} separator is the same as an empty String (""). 3930 * Null objects or empty strings within the array are represented by 3931 * empty strings.</p> 3932 * 3933 * <pre> 3934 * StringUtils.join(null, *) = null 3935 * StringUtils.join([], *) = "" 3936 * StringUtils.join([null], *) = "" 3937 * StringUtils.join(["a", "b", "c"], "--") = "a--b--c" 3938 * StringUtils.join(["a", "b", "c"], null) = "abc" 3939 * StringUtils.join(["a", "b", "c"], "") = "abc" 3940 * StringUtils.join([null, "", "a"], ',') = ",,a" 3941 * </pre> 3942 * 3943 * @param array the array of values to join together, may be null 3944 * @param separator the separator character to use, null treated as "" 3945 * @return the joined String, {@code null} if null array input 3946 */ 3947 public static String join(final Object[] array, final String separator) { 3948 if (array == null) { 3949 return null; 3950 } 3951 return join(array, separator, 0, array.length); 3952 } 3953 3954 /** 3955 * <p>Joins the elements of the provided array into a single String 3956 * containing the provided list of elements.</p> 3957 * 3958 * <p>No delimiter is added before or after the list. 3959 * A {@code null} separator is the same as an empty String (""). 3960 * Null objects or empty strings within the array are represented by 3961 * empty strings.</p> 3962 * 3963 * <pre> 3964 * StringUtils.join(null, *, *, *) = null 3965 * StringUtils.join([], *, *, *) = "" 3966 * StringUtils.join([null], *, *, *) = "" 3967 * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c" 3968 * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c" 3969 * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c" 3970 * StringUtils.join(["a", "b", "c"], "--", 2, 2) = "" 3971 * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc" 3972 * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc" 3973 * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a" 3974 * </pre> 3975 * 3976 * @param array the array of values to join together, may be null 3977 * @param separator the separator character to use, null treated as "" 3978 * @param startIndex the first index to start joining from. 3979 * @param endIndex the index to stop joining from (exclusive). 3980 * @return the joined String, {@code null} if null array input; or the empty string 3981 * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by 3982 * {@code endIndex - startIndex} 3983 * @throws ArrayIndexOutOfBoundsException ife<br/> 3984 * {@code startIndex < 0} or <br/> 3985 * {@code startIndex >= array.length()} or <br/> 3986 * {@code endIndex < 0} or <br/> 3987 * {@code endIndex > array.length()} 3988 */ 3989 public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) { 3990 if (array == null) { 3991 return null; 3992 } 3993 if (separator == null) { 3994 separator = EMPTY; 3995 } 3996 3997 // endIndex - startIndex > 0: Len = NofStrings *(len(firstString) + len(separator)) 3998 // (Assuming that all Strings are roughly equally long) 3999 final int noOfItems = endIndex - startIndex; 4000 if (noOfItems <= 0) { 4001 return EMPTY; 4002 } 4003 4004 final StringBuilder buf = new StringBuilder(noOfItems * 16); 4005 4006 for (int i = startIndex; i < endIndex; i++) { 4007 if (i > startIndex) { 4008 buf.append(separator); 4009 } 4010 if (array[i] != null) { 4011 buf.append(array[i]); 4012 } 4013 } 4014 return buf.toString(); 4015 } 4016 4017 /** 4018 * <p>Joins the elements of the provided {@code Iterator} into 4019 * a single String containing the provided elements.</p> 4020 * 4021 * <p>No delimiter is added before or after the list. Null objects or empty 4022 * strings within the iteration are represented by empty strings.</p> 4023 * 4024 * <p>See the examples here: {@link #join(Object[],char)}. </p> 4025 * 4026 * @param iterator the {@code Iterator} of values to join together, may be null 4027 * @param separator the separator character to use 4028 * @return the joined String, {@code null} if null iterator input 4029 * @since 2.0 4030 */ 4031 public static String join(final Iterator<?> iterator, final char separator) { 4032 4033 // handle null, zero and one elements before building a buffer 4034 if (iterator == null) { 4035 return null; 4036 } 4037 if (!iterator.hasNext()) { 4038 return EMPTY; 4039 } 4040 final Object first = iterator.next(); 4041 if (!iterator.hasNext()) { 4042 return ObjectUtils.toString(first); 4043 } 4044 4045 // two or more elements 4046 final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small 4047 if (first != null) { 4048 buf.append(first); 4049 } 4050 4051 while (iterator.hasNext()) { 4052 buf.append(separator); 4053 final Object obj = iterator.next(); 4054 if (obj != null) { 4055 buf.append(obj); 4056 } 4057 } 4058 4059 return buf.toString(); 4060 } 4061 4062 /** 4063 * <p>Joins the elements of the provided {@code Iterator} into 4064 * a single String containing the provided elements.</p> 4065 * 4066 * <p>No delimiter is added before or after the list. 4067 * A {@code null} separator is the same as an empty String ("").</p> 4068 * 4069 * <p>See the examples here: {@link #join(Object[],String)}. </p> 4070 * 4071 * @param iterator the {@code Iterator} of values to join together, may be null 4072 * @param separator the separator character to use, null treated as "" 4073 * @return the joined String, {@code null} if null iterator input 4074 */ 4075 public static String join(final Iterator<?> iterator, final String separator) { 4076 4077 // handle null, zero and one elements before building a buffer 4078 if (iterator == null) { 4079 return null; 4080 } 4081 if (!iterator.hasNext()) { 4082 return EMPTY; 4083 } 4084 final Object first = iterator.next(); 4085 if (!iterator.hasNext()) { 4086 return ObjectUtils.toString(first); 4087 } 4088 4089 // two or more elements 4090 final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small 4091 if (first != null) { 4092 buf.append(first); 4093 } 4094 4095 while (iterator.hasNext()) { 4096 if (separator != null) { 4097 buf.append(separator); 4098 } 4099 final Object obj = iterator.next(); 4100 if (obj != null) { 4101 buf.append(obj); 4102 } 4103 } 4104 return buf.toString(); 4105 } 4106 4107 /** 4108 * <p>Joins the elements of the provided {@code Iterable} into 4109 * a single String containing the provided elements.</p> 4110 * 4111 * <p>No delimiter is added before or after the list. Null objects or empty 4112 * strings within the iteration are represented by empty strings.</p> 4113 * 4114 * <p>See the examples here: {@link #join(Object[],char)}. </p> 4115 * 4116 * @param iterable the {@code Iterable} providing the values to join together, may be null 4117 * @param separator the separator character to use 4118 * @return the joined String, {@code null} if null iterator input 4119 * @since 2.3 4120 */ 4121 public static String join(final Iterable<?> iterable, final char separator) { 4122 if (iterable == null) { 4123 return null; 4124 } 4125 return join(iterable.iterator(), separator); 4126 } 4127 4128 /** 4129 * <p>Joins the elements of the provided {@code Iterable} into 4130 * a single String containing the provided elements.</p> 4131 * 4132 * <p>No delimiter is added before or after the list. 4133 * A {@code null} separator is the same as an empty String ("").</p> 4134 * 4135 * <p>See the examples here: {@link #join(Object[],String)}. </p> 4136 * 4137 * @param iterable the {@code Iterable} providing the values to join together, may be null 4138 * @param separator the separator character to use, null treated as "" 4139 * @return the joined String, {@code null} if null iterator input 4140 * @since 2.3 4141 */ 4142 public static String join(final Iterable<?> iterable, final String separator) { 4143 if (iterable == null) { 4144 return null; 4145 } 4146 return join(iterable.iterator(), separator); 4147 } 4148 4149 // Delete 4150 //----------------------------------------------------------------------- 4151 /** 4152 * <p>Deletes all whitespaces from a String as defined by 4153 * {@link Character#isWhitespace(char)}.</p> 4154 * 4155 * <pre> 4156 * StringUtils.deleteWhitespace(null) = null 4157 * StringUtils.deleteWhitespace("") = "" 4158 * StringUtils.deleteWhitespace("abc") = "abc" 4159 * StringUtils.deleteWhitespace(" ab c ") = "abc" 4160 * </pre> 4161 * 4162 * @param str the String to delete whitespace from, may be null 4163 * @return the String without whitespaces, {@code null} if null String input 4164 */ 4165 public static String deleteWhitespace(final String str) { 4166 if (isEmpty(str)) { 4167 return str; 4168 } 4169 final int sz = str.length(); 4170 final char[] chs = new char[sz]; 4171 int count = 0; 4172 for (int i = 0; i < sz; i++) { 4173 if (!Character.isWhitespace(str.charAt(i))) { 4174 chs[count++] = str.charAt(i); 4175 } 4176 } 4177 if (count == sz) { 4178 return str; 4179 } 4180 return new String(chs, 0, count); 4181 } 4182 4183 // Remove 4184 //----------------------------------------------------------------------- 4185 /** 4186 * <p>Removes a substring only if it is at the beginning of a source string, 4187 * otherwise returns the source string.</p> 4188 * 4189 * <p>A {@code null} source string will return {@code null}. 4190 * An empty ("") source string will return the empty string. 4191 * A {@code null} search string will return the source string.</p> 4192 * 4193 * <pre> 4194 * StringUtils.removeStart(null, *) = null 4195 * StringUtils.removeStart("", *) = "" 4196 * StringUtils.removeStart(*, null) = * 4197 * StringUtils.removeStart("www.domain.com", "www.") = "domain.com" 4198 * StringUtils.removeStart("domain.com", "www.") = "domain.com" 4199 * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com" 4200 * StringUtils.removeStart("abc", "") = "abc" 4201 * </pre> 4202 * 4203 * @param str the source String to search, may be null 4204 * @param remove the String to search for and remove, may be null 4205 * @return the substring with the string removed if found, 4206 * {@code null} if null String input 4207 * @since 2.1 4208 */ 4209 public static String removeStart(final String str, final String remove) { 4210 if (isEmpty(str) || isEmpty(remove)) { 4211 return str; 4212 } 4213 if (str.startsWith(remove)){ 4214 return str.substring(remove.length()); 4215 } 4216 return str; 4217 } 4218 4219 /** 4220 * <p>Case insensitive removal of a substring if it is at the beginning of a source string, 4221 * otherwise returns the source string.</p> 4222 * 4223 * <p>A {@code null} source string will return {@code null}. 4224 * An empty ("") source string will return the empty string. 4225 * A {@code null} search string will return the source string.</p> 4226 * 4227 * <pre> 4228 * StringUtils.removeStartIgnoreCase(null, *) = null 4229 * StringUtils.removeStartIgnoreCase("", *) = "" 4230 * StringUtils.removeStartIgnoreCase(*, null) = * 4231 * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com" 4232 * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com" 4233 * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com" 4234 * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com" 4235 * StringUtils.removeStartIgnoreCase("abc", "") = "abc" 4236 * </pre> 4237 * 4238 * @param str the source String to search, may be null 4239 * @param remove the String to search for (case insensitive) and remove, may be null 4240 * @return the substring with the string removed if found, 4241 * {@code null} if null String input 4242 * @since 2.4 4243 */ 4244 public static String removeStartIgnoreCase(final String str, final String remove) { 4245 if (isEmpty(str) || isEmpty(remove)) { 4246 return str; 4247 } 4248 if (startsWithIgnoreCase(str, remove)) { 4249 return str.substring(remove.length()); 4250 } 4251 return str; 4252 } 4253 4254 /** 4255 * <p>Removes a substring only if it is at the end of a source string, 4256 * otherwise returns the source string.</p> 4257 * 4258 * <p>A {@code null} source string will return {@code null}. 4259 * An empty ("") source string will return the empty string. 4260 * A {@code null} search string will return the source string.</p> 4261 * 4262 * <pre> 4263 * StringUtils.removeEnd(null, *) = null 4264 * StringUtils.removeEnd("", *) = "" 4265 * StringUtils.removeEnd(*, null) = * 4266 * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com" 4267 * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain" 4268 * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com" 4269 * StringUtils.removeEnd("abc", "") = "abc" 4270 * </pre> 4271 * 4272 * @param str the source String to search, may be null 4273 * @param remove the String to search for and remove, may be null 4274 * @return the substring with the string removed if found, 4275 * {@code null} if null String input 4276 * @since 2.1 4277 */ 4278 public static String removeEnd(final String str, final String remove) { 4279 if (isEmpty(str) || isEmpty(remove)) { 4280 return str; 4281 } 4282 if (str.endsWith(remove)) { 4283 return str.substring(0, str.length() - remove.length()); 4284 } 4285 return str; 4286 } 4287 4288 /** 4289 * <p>Case insensitive removal of a substring if it is at the end of a source string, 4290 * otherwise returns the source string.</p> 4291 * 4292 * <p>A {@code null} source string will return {@code null}. 4293 * An empty ("") source string will return the empty string. 4294 * A {@code null} search string will return the source string.</p> 4295 * 4296 * <pre> 4297 * StringUtils.removeEndIgnoreCase(null, *) = null 4298 * StringUtils.removeEndIgnoreCase("", *) = "" 4299 * StringUtils.removeEndIgnoreCase(*, null) = * 4300 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com" 4301 * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain" 4302 * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com" 4303 * StringUtils.removeEndIgnoreCase("abc", "") = "abc" 4304 * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain") 4305 * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain") 4306 * </pre> 4307 * 4308 * @param str the source String to search, may be null 4309 * @param remove the String to search for (case insensitive) and remove, may be null 4310 * @return the substring with the string removed if found, 4311 * {@code null} if null String input 4312 * @since 2.4 4313 */ 4314 public static String removeEndIgnoreCase(final String str, final String remove) { 4315 if (isEmpty(str) || isEmpty(remove)) { 4316 return str; 4317 } 4318 if (endsWithIgnoreCase(str, remove)) { 4319 return str.substring(0, str.length() - remove.length()); 4320 } 4321 return str; 4322 } 4323 4324 /** 4325 * <p>Removes all occurrences of a substring from within the source string.</p> 4326 * 4327 * <p>A {@code null} source string will return {@code null}. 4328 * An empty ("") source string will return the empty string. 4329 * A {@code null} remove string will return the source string. 4330 * An empty ("") remove string will return the source string.</p> 4331 * 4332 * <pre> 4333 * StringUtils.remove(null, *) = null 4334 * StringUtils.remove("", *) = "" 4335 * StringUtils.remove(*, null) = * 4336 * StringUtils.remove(*, "") = * 4337 * StringUtils.remove("queued", "ue") = "qd" 4338 * StringUtils.remove("queued", "zz") = "queued" 4339 * </pre> 4340 * 4341 * @param str the source String to search, may be null 4342 * @param remove the String to search for and remove, may be null 4343 * @return the substring with the string removed if found, 4344 * {@code null} if null String input 4345 * @since 2.1 4346 */ 4347 public static String remove(final String str, final String remove) { 4348 if (isEmpty(str) || isEmpty(remove)) { 4349 return str; 4350 } 4351 return replace(str, remove, EMPTY, -1); 4352 } 4353 4354 /** 4355 * <p>Removes all occurrences of a character from within the source string.</p> 4356 * 4357 * <p>A {@code null} source string will return {@code null}. 4358 * An empty ("") source string will return the empty string.</p> 4359 * 4360 * <pre> 4361 * StringUtils.remove(null, *) = null 4362 * StringUtils.remove("", *) = "" 4363 * StringUtils.remove("queued", 'u') = "qeed" 4364 * StringUtils.remove("queued", 'z') = "queued" 4365 * </pre> 4366 * 4367 * @param str the source String to search, may be null 4368 * @param remove the char to search for and remove, may be null 4369 * @return the substring with the char removed if found, 4370 * {@code null} if null String input 4371 * @since 2.1 4372 */ 4373 public static String remove(final String str, final char remove) { 4374 if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) { 4375 return str; 4376 } 4377 final char[] chars = str.toCharArray(); 4378 int pos = 0; 4379 for (int i = 0; i < chars.length; i++) { 4380 if (chars[i] != remove) { 4381 chars[pos++] = chars[i]; 4382 } 4383 } 4384 return new String(chars, 0, pos); 4385 } 4386 4387 // Replacing 4388 //----------------------------------------------------------------------- 4389 /** 4390 * <p>Replaces a String with another String inside a larger String, once.</p> 4391 * 4392 * <p>A {@code null} reference passed to this method is a no-op.</p> 4393 * 4394 * <pre> 4395 * StringUtils.replaceOnce(null, *, *) = null 4396 * StringUtils.replaceOnce("", *, *) = "" 4397 * StringUtils.replaceOnce("any", null, *) = "any" 4398 * StringUtils.replaceOnce("any", *, null) = "any" 4399 * StringUtils.replaceOnce("any", "", *) = "any" 4400 * StringUtils.replaceOnce("aba", "a", null) = "aba" 4401 * StringUtils.replaceOnce("aba", "a", "") = "ba" 4402 * StringUtils.replaceOnce("aba", "a", "z") = "zba" 4403 * </pre> 4404 * 4405 * @see #replace(String text, String searchString, String replacement, int max) 4406 * @param text text to search and replace in, may be null 4407 * @param searchString the String to search for, may be null 4408 * @param replacement the String to replace with, may be null 4409 * @return the text with any replacements processed, 4410 * {@code null} if null String input 4411 */ 4412 public static String replaceOnce(final String text, final String searchString, final String replacement) { 4413 return replace(text, searchString, replacement, 1); 4414 } 4415 4416 /** 4417 * Replaces each substring of the source String that matches the given regular expression with the given 4418 * replacement using the {@link Pattern#DOTALL} option. DOTALL is also know as single-line mode in Perl. This call 4419 * is also equivalent to: 4420 * <ul> 4421 * <li>{@code source.replaceAll("(?s)" + regex, replacement)}</li> 4422 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li> 4423 * </ul> 4424 * 4425 * @param source 4426 * the source string 4427 * @param regex 4428 * the regular expression to which this string is to be matched 4429 * @param replacement 4430 * the string to be substituted for each match 4431 * @return The resulting {@code String} 4432 * @see String#replaceAll(String, String) 4433 * @see Pattern#DOTALL 4434 * @since 3.2 4435 */ 4436 public static String replacePattern(final String source, final String regex, final String replacement) { 4437 return Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement); 4438 } 4439 4440 /** 4441 * Removes each substring of the source String that matches the given regular expression using the DOTALL option. 4442 * 4443 * @param source 4444 * the source string 4445 * @param regex 4446 * the regular expression to which this string is to be matched 4447 * @return The resulting {@code String} 4448 * @see String#replaceAll(String, String) 4449 * @see Pattern#DOTALL 4450 * @since 3.2 4451 */ 4452 public static String removePattern(final String source, final String regex) { 4453 return replacePattern(source, regex, StringUtils.EMPTY); 4454 } 4455 4456 /** 4457 * <p>Replaces all occurrences of a String within another String.</p> 4458 * 4459 * <p>A {@code null} reference passed to this method is a no-op.</p> 4460 * 4461 * <pre> 4462 * StringUtils.replace(null, *, *) = null 4463 * StringUtils.replace("", *, *) = "" 4464 * StringUtils.replace("any", null, *) = "any" 4465 * StringUtils.replace("any", *, null) = "any" 4466 * StringUtils.replace("any", "", *) = "any" 4467 * StringUtils.replace("aba", "a", null) = "aba" 4468 * StringUtils.replace("aba", "a", "") = "b" 4469 * StringUtils.replace("aba", "a", "z") = "zbz" 4470 * </pre> 4471 * 4472 * @see #replace(String text, String searchString, String replacement, int max) 4473 * @param text text to search and replace in, may be null 4474 * @param searchString the String to search for, may be null 4475 * @param replacement the String to replace it with, may be null 4476 * @return the text with any replacements processed, 4477 * {@code null} if null String input 4478 */ 4479 public static String replace(final String text, final String searchString, final String replacement) { 4480 return replace(text, searchString, replacement, -1); 4481 } 4482 4483 /** 4484 * <p>Replaces a String with another String inside a larger String, 4485 * for the first {@code max} values of the search String.</p> 4486 * 4487 * <p>A {@code null} reference passed to this method is a no-op.</p> 4488 * 4489 * <pre> 4490 * StringUtils.replace(null, *, *, *) = null 4491 * StringUtils.replace("", *, *, *) = "" 4492 * StringUtils.replace("any", null, *, *) = "any" 4493 * StringUtils.replace("any", *, null, *) = "any" 4494 * StringUtils.replace("any", "", *, *) = "any" 4495 * StringUtils.replace("any", *, *, 0) = "any" 4496 * StringUtils.replace("abaa", "a", null, -1) = "abaa" 4497 * StringUtils.replace("abaa", "a", "", -1) = "b" 4498 * StringUtils.replace("abaa", "a", "z", 0) = "abaa" 4499 * StringUtils.replace("abaa", "a", "z", 1) = "zbaa" 4500 * StringUtils.replace("abaa", "a", "z", 2) = "zbza" 4501 * StringUtils.replace("abaa", "a", "z", -1) = "zbzz" 4502 * </pre> 4503 * 4504 * @param text text to search and replace in, may be null 4505 * @param searchString the String to search for, may be null 4506 * @param replacement the String to replace it with, may be null 4507 * @param max maximum number of values to replace, or {@code -1} if no maximum 4508 * @return the text with any replacements processed, 4509 * {@code null} if null String input 4510 */ 4511 public static String replace(final String text, final String searchString, final String replacement, int max) { 4512 if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) { 4513 return text; 4514 } 4515 int start = 0; 4516 int end = text.indexOf(searchString, start); 4517 if (end == INDEX_NOT_FOUND) { 4518 return text; 4519 } 4520 final int replLength = searchString.length(); 4521 int increase = replacement.length() - replLength; 4522 increase = increase < 0 ? 0 : increase; 4523 increase *= max < 0 ? 16 : max > 64 ? 64 : max; 4524 final StringBuilder buf = new StringBuilder(text.length() + increase); 4525 while (end != INDEX_NOT_FOUND) { 4526 buf.append(text.substring(start, end)).append(replacement); 4527 start = end + replLength; 4528 if (--max == 0) { 4529 break; 4530 } 4531 end = text.indexOf(searchString, start); 4532 } 4533 buf.append(text.substring(start)); 4534 return buf.toString(); 4535 } 4536 4537 /** 4538 * <p> 4539 * Replaces all occurrences of Strings within another String. 4540 * </p> 4541 * 4542 * <p> 4543 * A {@code null} reference passed to this method is a no-op, or if 4544 * any "search string" or "string to replace" is null, that replace will be 4545 * ignored. This will not repeat. For repeating replaces, call the 4546 * overloaded method. 4547 * </p> 4548 * 4549 * <pre> 4550 * StringUtils.replaceEach(null, *, *) = null 4551 * StringUtils.replaceEach("", *, *) = "" 4552 * StringUtils.replaceEach("aba", null, null) = "aba" 4553 * StringUtils.replaceEach("aba", new String[0], null) = "aba" 4554 * StringUtils.replaceEach("aba", null, new String[0]) = "aba" 4555 * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba" 4556 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b" 4557 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba" 4558 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte" 4559 * (example of how it does not repeat) 4560 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte" 4561 * </pre> 4562 * 4563 * @param text 4564 * text to search and replace in, no-op if null 4565 * @param searchList 4566 * the Strings to search for, no-op if null 4567 * @param replacementList 4568 * the Strings to replace them with, no-op if null 4569 * @return the text with any replacements processed, {@code null} if 4570 * null String input 4571 * @throws IllegalArgumentException 4572 * if the lengths of the arrays are not the same (null is ok, 4573 * and/or size 0) 4574 * @since 2.4 4575 */ 4576 public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) { 4577 return replaceEach(text, searchList, replacementList, false, 0); 4578 } 4579 4580 /** 4581 * <p> 4582 * Replaces all occurrences of Strings within another String. 4583 * </p> 4584 * 4585 * <p> 4586 * A {@code null} reference passed to this method is a no-op, or if 4587 * any "search string" or "string to replace" is null, that replace will be 4588 * ignored. 4589 * </p> 4590 * 4591 * <pre> 4592 * StringUtils.replaceEach(null, *, *, *) = null 4593 * StringUtils.replaceEach("", *, *, *) = "" 4594 * StringUtils.replaceEach("aba", null, null, *) = "aba" 4595 * StringUtils.replaceEach("aba", new String[0], null, *) = "aba" 4596 * StringUtils.replaceEach("aba", null, new String[0], *) = "aba" 4597 * StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba" 4598 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b" 4599 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba" 4600 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte" 4601 * (example of how it repeats) 4602 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte" 4603 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte" 4604 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, true) = IllegalStateException 4605 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, false) = "dcabe" 4606 * </pre> 4607 * 4608 * @param text 4609 * text to search and replace in, no-op if null 4610 * @param searchList 4611 * the Strings to search for, no-op if null 4612 * @param replacementList 4613 * the Strings to replace them with, no-op if null 4614 * @return the text with any replacements processed, {@code null} if 4615 * null String input 4616 * @throws IllegalStateException 4617 * if the search is repeating and there is an endless loop due 4618 * to outputs of one being inputs to another 4619 * @throws IllegalArgumentException 4620 * if the lengths of the arrays are not the same (null is ok, 4621 * and/or size 0) 4622 * @since 2.4 4623 */ 4624 public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) { 4625 // timeToLive should be 0 if not used or nothing to replace, else it's 4626 // the length of the replace array 4627 final int timeToLive = searchList == null ? 0 : searchList.length; 4628 return replaceEach(text, searchList, replacementList, true, timeToLive); 4629 } 4630 4631 /** 4632 * <p> 4633 * Replaces all occurrences of Strings within another String. 4634 * </p> 4635 * 4636 * <p> 4637 * A {@code null} reference passed to this method is a no-op, or if 4638 * any "search string" or "string to replace" is null, that replace will be 4639 * ignored. 4640 * </p> 4641 * 4642 * <pre> 4643 * StringUtils.replaceEach(null, *, *, *) = null 4644 * StringUtils.replaceEach("", *, *, *) = "" 4645 * StringUtils.replaceEach("aba", null, null, *) = "aba" 4646 * StringUtils.replaceEach("aba", new String[0], null, *) = "aba" 4647 * StringUtils.replaceEach("aba", null, new String[0], *) = "aba" 4648 * StringUtils.replaceEach("aba", new String[]{"a"}, null, *) = "aba" 4649 * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *) = "b" 4650 * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *) = "aba" 4651 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *) = "wcte" 4652 * (example of how it repeats) 4653 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false) = "dcte" 4654 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true) = "tcte" 4655 * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *) = IllegalStateException 4656 * </pre> 4657 * 4658 * @param text 4659 * text to search and replace in, no-op if null 4660 * @param searchList 4661 * the Strings to search for, no-op if null 4662 * @param replacementList 4663 * the Strings to replace them with, no-op if null 4664 * @param repeat if true, then replace repeatedly 4665 * until there are no more possible replacements or timeToLive < 0 4666 * @param timeToLive 4667 * if less than 0 then there is a circular reference and endless 4668 * loop 4669 * @return the text with any replacements processed, {@code null} if 4670 * null String input 4671 * @throws IllegalStateException 4672 * if the search is repeating and there is an endless loop due 4673 * to outputs of one being inputs to another 4674 * @throws IllegalArgumentException 4675 * if the lengths of the arrays are not the same (null is ok, 4676 * and/or size 0) 4677 * @since 2.4 4678 */ 4679 private static String replaceEach( 4680 final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) { 4681 4682 // mchyzer Performance note: This creates very few new objects (one major goal) 4683 // let me know if there are performance requests, we can create a harness to measure 4684 4685 if (text == null || text.isEmpty() || searchList == null || 4686 searchList.length == 0 || replacementList == null || replacementList.length == 0) { 4687 return text; 4688 } 4689 4690 // if recursing, this shouldn't be less than 0 4691 if (timeToLive < 0) { 4692 throw new IllegalStateException("Aborting to protect against StackOverflowError - " + 4693 "output of one loop is the input of another"); 4694 } 4695 4696 final int searchLength = searchList.length; 4697 final int replacementLength = replacementList.length; 4698 4699 // make sure lengths are ok, these need to be equal 4700 if (searchLength != replacementLength) { 4701 throw new IllegalArgumentException("Search and Replace array lengths don't match: " 4702 + searchLength 4703 + " vs " 4704 + replacementLength); 4705 } 4706 4707 // keep track of which still have matches 4708 final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength]; 4709 4710 // index on index that the match was found 4711 int textIndex = -1; 4712 int replaceIndex = -1; 4713 int tempIndex = -1; 4714 4715 // index of replace array that will replace the search string found 4716 // NOTE: logic duplicated below START 4717 for (int i = 0; i < searchLength; i++) { 4718 if (noMoreMatchesForReplIndex[i] || searchList[i] == null || 4719 searchList[i].isEmpty() || replacementList[i] == null) { 4720 continue; 4721 } 4722 tempIndex = text.indexOf(searchList[i]); 4723 4724 // see if we need to keep searching for this 4725 if (tempIndex == -1) { 4726 noMoreMatchesForReplIndex[i] = true; 4727 } else { 4728 if (textIndex == -1 || tempIndex < textIndex) { 4729 textIndex = tempIndex; 4730 replaceIndex = i; 4731 } 4732 } 4733 } 4734 // NOTE: logic mostly below END 4735 4736 // no search strings found, we are done 4737 if (textIndex == -1) { 4738 return text; 4739 } 4740 4741 int start = 0; 4742 4743 // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit 4744 int increase = 0; 4745 4746 // count the replacement text elements that are larger than their corresponding text being replaced 4747 for (int i = 0; i < searchList.length; i++) { 4748 if (searchList[i] == null || replacementList[i] == null) { 4749 continue; 4750 } 4751 final int greater = replacementList[i].length() - searchList[i].length(); 4752 if (greater > 0) { 4753 increase += 3 * greater; // assume 3 matches 4754 } 4755 } 4756 // have upper-bound at 20% increase, then let Java take over 4757 increase = Math.min(increase, text.length() / 5); 4758 4759 final StringBuilder buf = new StringBuilder(text.length() + increase); 4760 4761 while (textIndex != -1) { 4762 4763 for (int i = start; i < textIndex; i++) { 4764 buf.append(text.charAt(i)); 4765 } 4766 buf.append(replacementList[replaceIndex]); 4767 4768 start = textIndex + searchList[replaceIndex].length(); 4769 4770 textIndex = -1; 4771 replaceIndex = -1; 4772 tempIndex = -1; 4773 // find the next earliest match 4774 // NOTE: logic mostly duplicated above START 4775 for (int i = 0; i < searchLength; i++) { 4776 if (noMoreMatchesForReplIndex[i] || searchList[i] == null || 4777 searchList[i].isEmpty() || replacementList[i] == null) { 4778 continue; 4779 } 4780 tempIndex = text.indexOf(searchList[i], start); 4781 4782 // see if we need to keep searching for this 4783 if (tempIndex == -1) { 4784 noMoreMatchesForReplIndex[i] = true; 4785 } else { 4786 if (textIndex == -1 || tempIndex < textIndex) { 4787 textIndex = tempIndex; 4788 replaceIndex = i; 4789 } 4790 } 4791 } 4792 // NOTE: logic duplicated above END 4793 4794 } 4795 final int textLength = text.length(); 4796 for (int i = start; i < textLength; i++) { 4797 buf.append(text.charAt(i)); 4798 } 4799 final String result = buf.toString(); 4800 if (!repeat) { 4801 return result; 4802 } 4803 4804 return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1); 4805 } 4806 4807 // Replace, character based 4808 //----------------------------------------------------------------------- 4809 /** 4810 * <p>Replaces all occurrences of a character in a String with another. 4811 * This is a null-safe version of {@link String#replace(char, char)}.</p> 4812 * 4813 * <p>A {@code null} string input returns {@code null}. 4814 * An empty ("") string input returns an empty string.</p> 4815 * 4816 * <pre> 4817 * StringUtils.replaceChars(null, *, *) = null 4818 * StringUtils.replaceChars("", *, *) = "" 4819 * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya" 4820 * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba" 4821 * </pre> 4822 * 4823 * @param str String to replace characters in, may be null 4824 * @param searchChar the character to search for, may be null 4825 * @param replaceChar the character to replace, may be null 4826 * @return modified String, {@code null} if null string input 4827 * @since 2.0 4828 */ 4829 public static String replaceChars(final String str, final char searchChar, final char replaceChar) { 4830 if (str == null) { 4831 return null; 4832 } 4833 return str.replace(searchChar, replaceChar); 4834 } 4835 4836 /** 4837 * <p>Replaces multiple characters in a String in one go. 4838 * This method can also be used to delete characters.</p> 4839 * 4840 * <p>For example:<br /> 4841 * <code>replaceChars("hello", "ho", "jy") = jelly</code>.</p> 4842 * 4843 * <p>A {@code null} string input returns {@code null}. 4844 * An empty ("") string input returns an empty string. 4845 * A null or empty set of search characters returns the input string.</p> 4846 * 4847 * <p>The length of the search characters should normally equal the length 4848 * of the replace characters. 4849 * If the search characters is longer, then the extra search characters 4850 * are deleted. 4851 * If the search characters is shorter, then the extra replace characters 4852 * are ignored.</p> 4853 * 4854 * <pre> 4855 * StringUtils.replaceChars(null, *, *) = null 4856 * StringUtils.replaceChars("", *, *) = "" 4857 * StringUtils.replaceChars("abc", null, *) = "abc" 4858 * StringUtils.replaceChars("abc", "", *) = "abc" 4859 * StringUtils.replaceChars("abc", "b", null) = "ac" 4860 * StringUtils.replaceChars("abc", "b", "") = "ac" 4861 * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya" 4862 * StringUtils.replaceChars("abcba", "bc", "y") = "ayya" 4863 * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya" 4864 * </pre> 4865 * 4866 * @param str String to replace characters in, may be null 4867 * @param searchChars a set of characters to search for, may be null 4868 * @param replaceChars a set of characters to replace, may be null 4869 * @return modified String, {@code null} if null string input 4870 * @since 2.0 4871 */ 4872 public static String replaceChars(final String str, final String searchChars, String replaceChars) { 4873 if (isEmpty(str) || isEmpty(searchChars)) { 4874 return str; 4875 } 4876 if (replaceChars == null) { 4877 replaceChars = EMPTY; 4878 } 4879 boolean modified = false; 4880 final int replaceCharsLength = replaceChars.length(); 4881 final int strLength = str.length(); 4882 final StringBuilder buf = new StringBuilder(strLength); 4883 for (int i = 0; i < strLength; i++) { 4884 final char ch = str.charAt(i); 4885 final int index = searchChars.indexOf(ch); 4886 if (index >= 0) { 4887 modified = true; 4888 if (index < replaceCharsLength) { 4889 buf.append(replaceChars.charAt(index)); 4890 } 4891 } else { 4892 buf.append(ch); 4893 } 4894 } 4895 if (modified) { 4896 return buf.toString(); 4897 } 4898 return str; 4899 } 4900 4901 // Overlay 4902 //----------------------------------------------------------------------- 4903 /** 4904 * <p>Overlays part of a String with another String.</p> 4905 * 4906 * <p>A {@code null} string input returns {@code null}. 4907 * A negative index is treated as zero. 4908 * An index greater than the string length is treated as the string length. 4909 * The start index is always the smaller of the two indices.</p> 4910 * 4911 * <pre> 4912 * StringUtils.overlay(null, *, *, *) = null 4913 * StringUtils.overlay("", "abc", 0, 0) = "abc" 4914 * StringUtils.overlay("abcdef", null, 2, 4) = "abef" 4915 * StringUtils.overlay("abcdef", "", 2, 4) = "abef" 4916 * StringUtils.overlay("abcdef", "", 4, 2) = "abef" 4917 * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef" 4918 * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef" 4919 * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef" 4920 * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz" 4921 * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef" 4922 * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz" 4923 * </pre> 4924 * 4925 * @param str the String to do overlaying in, may be null 4926 * @param overlay the String to overlay, may be null 4927 * @param start the position to start overlaying at 4928 * @param end the position to stop overlaying before 4929 * @return overlayed String, {@code null} if null String input 4930 * @since 2.0 4931 */ 4932 public static String overlay(final String str, String overlay, int start, int end) { 4933 if (str == null) { 4934 return null; 4935 } 4936 if (overlay == null) { 4937 overlay = EMPTY; 4938 } 4939 final int len = str.length(); 4940 if (start < 0) { 4941 start = 0; 4942 } 4943 if (start > len) { 4944 start = len; 4945 } 4946 if (end < 0) { 4947 end = 0; 4948 } 4949 if (end > len) { 4950 end = len; 4951 } 4952 if (start > end) { 4953 final int temp = start; 4954 start = end; 4955 end = temp; 4956 } 4957 return new StringBuilder(len + start - end + overlay.length() + 1) 4958 .append(str.substring(0, start)) 4959 .append(overlay) 4960 .append(str.substring(end)) 4961 .toString(); 4962 } 4963 4964 // Chomping 4965 //----------------------------------------------------------------------- 4966 /** 4967 * <p>Removes one newline from end of a String if it's there, 4968 * otherwise leave it alone. A newline is "{@code \n}", 4969 * "{@code \r}", or "{@code \r\n}".</p> 4970 * 4971 * <p>NOTE: This method changed in 2.0. 4972 * It now more closely matches Perl chomp.</p> 4973 * 4974 * <pre> 4975 * StringUtils.chomp(null) = null 4976 * StringUtils.chomp("") = "" 4977 * StringUtils.chomp("abc \r") = "abc " 4978 * StringUtils.chomp("abc\n") = "abc" 4979 * StringUtils.chomp("abc\r\n") = "abc" 4980 * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n" 4981 * StringUtils.chomp("abc\n\r") = "abc\n" 4982 * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc" 4983 * StringUtils.chomp("\r") = "" 4984 * StringUtils.chomp("\n") = "" 4985 * StringUtils.chomp("\r\n") = "" 4986 * </pre> 4987 * 4988 * @param str the String to chomp a newline from, may be null 4989 * @return String without newline, {@code null} if null String input 4990 */ 4991 public static String chomp(final String str) { 4992 if (isEmpty(str)) { 4993 return str; 4994 } 4995 4996 if (str.length() == 1) { 4997 final char ch = str.charAt(0); 4998 if (ch == CharUtils.CR || ch == CharUtils.LF) { 4999 return EMPTY; 5000 } 5001 return str; 5002 } 5003 5004 int lastIdx = str.length() - 1; 5005 final char last = str.charAt(lastIdx); 5006 5007 if (last == CharUtils.LF) { 5008 if (str.charAt(lastIdx - 1) == CharUtils.CR) { 5009 lastIdx--; 5010 } 5011 } else if (last != CharUtils.CR) { 5012 lastIdx++; 5013 } 5014 return str.substring(0, lastIdx); 5015 } 5016 5017 /** 5018 * <p>Removes {@code separator} from the end of 5019 * {@code str} if it's there, otherwise leave it alone.</p> 5020 * 5021 * <p>NOTE: This method changed in version 2.0. 5022 * It now more closely matches Perl chomp. 5023 * For the previous behavior, use {@link #substringBeforeLast(String, String)}. 5024 * This method uses {@link String#endsWith(String)}.</p> 5025 * 5026 * <pre> 5027 * StringUtils.chomp(null, *) = null 5028 * StringUtils.chomp("", *) = "" 5029 * StringUtils.chomp("foobar", "bar") = "foo" 5030 * StringUtils.chomp("foobar", "baz") = "foobar" 5031 * StringUtils.chomp("foo", "foo") = "" 5032 * StringUtils.chomp("foo ", "foo") = "foo " 5033 * StringUtils.chomp(" foo", "foo") = " " 5034 * StringUtils.chomp("foo", "foooo") = "foo" 5035 * StringUtils.chomp("foo", "") = "foo" 5036 * StringUtils.chomp("foo", null) = "foo" 5037 * </pre> 5038 * 5039 * @param str the String to chomp from, may be null 5040 * @param separator separator String, may be null 5041 * @return String without trailing separator, {@code null} if null String input 5042 * @deprecated This feature will be removed in Lang 4.0, use {@link StringUtils#removeEnd(String, String)} instead 5043 */ 5044 @Deprecated 5045 public static String chomp(final String str, final String separator) { 5046 return removeEnd(str,separator); 5047 } 5048 5049 // Chopping 5050 //----------------------------------------------------------------------- 5051 /** 5052 * <p>Remove the last character from a String.</p> 5053 * 5054 * <p>If the String ends in {@code \r\n}, then remove both 5055 * of them.</p> 5056 * 5057 * <pre> 5058 * StringUtils.chop(null) = null 5059 * StringUtils.chop("") = "" 5060 * StringUtils.chop("abc \r") = "abc " 5061 * StringUtils.chop("abc\n") = "abc" 5062 * StringUtils.chop("abc\r\n") = "abc" 5063 * StringUtils.chop("abc") = "ab" 5064 * StringUtils.chop("abc\nabc") = "abc\nab" 5065 * StringUtils.chop("a") = "" 5066 * StringUtils.chop("\r") = "" 5067 * StringUtils.chop("\n") = "" 5068 * StringUtils.chop("\r\n") = "" 5069 * </pre> 5070 * 5071 * @param str the String to chop last character from, may be null 5072 * @return String without last character, {@code null} if null String input 5073 */ 5074 public static String chop(final String str) { 5075 if (str == null) { 5076 return null; 5077 } 5078 final int strLen = str.length(); 5079 if (strLen < 2) { 5080 return EMPTY; 5081 } 5082 final int lastIdx = strLen - 1; 5083 final String ret = str.substring(0, lastIdx); 5084 final char last = str.charAt(lastIdx); 5085 if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) { 5086 return ret.substring(0, lastIdx - 1); 5087 } 5088 return ret; 5089 } 5090 5091 // Conversion 5092 //----------------------------------------------------------------------- 5093 5094 // Padding 5095 //----------------------------------------------------------------------- 5096 /** 5097 * <p>Repeat a String {@code repeat} times to form a 5098 * new String.</p> 5099 * 5100 * <pre> 5101 * StringUtils.repeat(null, 2) = null 5102 * StringUtils.repeat("", 0) = "" 5103 * StringUtils.repeat("", 2) = "" 5104 * StringUtils.repeat("a", 3) = "aaa" 5105 * StringUtils.repeat("ab", 2) = "abab" 5106 * StringUtils.repeat("a", -2) = "" 5107 * </pre> 5108 * 5109 * @param str the String to repeat, may be null 5110 * @param repeat number of times to repeat str, negative treated as zero 5111 * @return a new String consisting of the original String repeated, 5112 * {@code null} if null String input 5113 */ 5114 public static String repeat(final String str, final int repeat) { 5115 // Performance tuned for 2.0 (JDK1.4) 5116 5117 if (str == null) { 5118 return null; 5119 } 5120 if (repeat <= 0) { 5121 return EMPTY; 5122 } 5123 final int inputLength = str.length(); 5124 if (repeat == 1 || inputLength == 0) { 5125 return str; 5126 } 5127 if (inputLength == 1 && repeat <= PAD_LIMIT) { 5128 return repeat(str.charAt(0), repeat); 5129 } 5130 5131 final int outputLength = inputLength * repeat; 5132 switch (inputLength) { 5133 case 1 : 5134 return repeat(str.charAt(0), repeat); 5135 case 2 : 5136 final char ch0 = str.charAt(0); 5137 final char ch1 = str.charAt(1); 5138 final char[] output2 = new char[outputLength]; 5139 for (int i = repeat * 2 - 2; i >= 0; i--, i--) { 5140 output2[i] = ch0; 5141 output2[i + 1] = ch1; 5142 } 5143 return new String(output2); 5144 default : 5145 final StringBuilder buf = new StringBuilder(outputLength); 5146 for (int i = 0; i < repeat; i++) { 5147 buf.append(str); 5148 } 5149 return buf.toString(); 5150 } 5151 } 5152 5153 /** 5154 * <p>Repeat a String {@code repeat} times to form a 5155 * new String, with a String separator injected each time. </p> 5156 * 5157 * <pre> 5158 * StringUtils.repeat(null, null, 2) = null 5159 * StringUtils.repeat(null, "x", 2) = null 5160 * StringUtils.repeat("", null, 0) = "" 5161 * StringUtils.repeat("", "", 2) = "" 5162 * StringUtils.repeat("", "x", 3) = "xxx" 5163 * StringUtils.repeat("?", ", ", 3) = "?, ?, ?" 5164 * </pre> 5165 * 5166 * @param str the String to repeat, may be null 5167 * @param separator the String to inject, may be null 5168 * @param repeat number of times to repeat str, negative treated as zero 5169 * @return a new String consisting of the original String repeated, 5170 * {@code null} if null String input 5171 * @since 2.5 5172 */ 5173 public static String repeat(final String str, final String separator, final int repeat) { 5174 if(str == null || separator == null) { 5175 return repeat(str, repeat); 5176 } 5177 // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it 5178 final String result = repeat(str + separator, repeat); 5179 return removeEnd(result, separator); 5180 } 5181 5182 /** 5183 * <p>Returns padding using the specified delimiter repeated 5184 * to a given length.</p> 5185 * 5186 * <pre> 5187 * StringUtils.repeat('e', 0) = "" 5188 * StringUtils.repeat('e', 3) = "eee" 5189 * StringUtils.repeat('e', -2) = "" 5190 * </pre> 5191 * 5192 * <p>Note: this method doesn't not support padding with 5193 * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a> 5194 * as they require a pair of {@code char}s to be represented. 5195 * If you are needing to support full I18N of your applications 5196 * consider using {@link #repeat(String, int)} instead. 5197 * </p> 5198 * 5199 * @param ch character to repeat 5200 * @param repeat number of times to repeat char, negative treated as zero 5201 * @return String with repeated character 5202 * @see #repeat(String, int) 5203 */ 5204 public static String repeat(final char ch, final int repeat) { 5205 final char[] buf = new char[repeat]; 5206 for (int i = repeat - 1; i >= 0; i--) { 5207 buf[i] = ch; 5208 } 5209 return new String(buf); 5210 } 5211 5212 /** 5213 * <p>Right pad a String with spaces (' ').</p> 5214 * 5215 * <p>The String is padded to the size of {@code size}.</p> 5216 * 5217 * <pre> 5218 * StringUtils.rightPad(null, *) = null 5219 * StringUtils.rightPad("", 3) = " " 5220 * StringUtils.rightPad("bat", 3) = "bat" 5221 * StringUtils.rightPad("bat", 5) = "bat " 5222 * StringUtils.rightPad("bat", 1) = "bat" 5223 * StringUtils.rightPad("bat", -1) = "bat" 5224 * </pre> 5225 * 5226 * @param str the String to pad out, may be null 5227 * @param size the size to pad to 5228 * @return right padded String or original String if no padding is necessary, 5229 * {@code null} if null String input 5230 */ 5231 public static String rightPad(final String str, final int size) { 5232 return rightPad(str, size, ' '); 5233 } 5234 5235 /** 5236 * <p>Right pad a String with a specified character.</p> 5237 * 5238 * <p>The String is padded to the size of {@code size}.</p> 5239 * 5240 * <pre> 5241 * StringUtils.rightPad(null, *, *) = null 5242 * StringUtils.rightPad("", 3, 'z') = "zzz" 5243 * StringUtils.rightPad("bat", 3, 'z') = "bat" 5244 * StringUtils.rightPad("bat", 5, 'z') = "batzz" 5245 * StringUtils.rightPad("bat", 1, 'z') = "bat" 5246 * StringUtils.rightPad("bat", -1, 'z') = "bat" 5247 * </pre> 5248 * 5249 * @param str the String to pad out, may be null 5250 * @param size the size to pad to 5251 * @param padChar the character to pad with 5252 * @return right padded String or original String if no padding is necessary, 5253 * {@code null} if null String input 5254 * @since 2.0 5255 */ 5256 public static String rightPad(final String str, final int size, final char padChar) { 5257 if (str == null) { 5258 return null; 5259 } 5260 final int pads = size - str.length(); 5261 if (pads <= 0) { 5262 return str; // returns original String when possible 5263 } 5264 if (pads > PAD_LIMIT) { 5265 return rightPad(str, size, String.valueOf(padChar)); 5266 } 5267 return str.concat(repeat(padChar, pads)); 5268 } 5269 5270 /** 5271 * <p>Right pad a String with a specified String.</p> 5272 * 5273 * <p>The String is padded to the size of {@code size}.</p> 5274 * 5275 * <pre> 5276 * StringUtils.rightPad(null, *, *) = null 5277 * StringUtils.rightPad("", 3, "z") = "zzz" 5278 * StringUtils.rightPad("bat", 3, "yz") = "bat" 5279 * StringUtils.rightPad("bat", 5, "yz") = "batyz" 5280 * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy" 5281 * StringUtils.rightPad("bat", 1, "yz") = "bat" 5282 * StringUtils.rightPad("bat", -1, "yz") = "bat" 5283 * StringUtils.rightPad("bat", 5, null) = "bat " 5284 * StringUtils.rightPad("bat", 5, "") = "bat " 5285 * </pre> 5286 * 5287 * @param str the String to pad out, may be null 5288 * @param size the size to pad to 5289 * @param padStr the String to pad with, null or empty treated as single space 5290 * @return right padded String or original String if no padding is necessary, 5291 * {@code null} if null String input 5292 */ 5293 public static String rightPad(final String str, final int size, String padStr) { 5294 if (str == null) { 5295 return null; 5296 } 5297 if (isEmpty(padStr)) { 5298 padStr = SPACE; 5299 } 5300 final int padLen = padStr.length(); 5301 final int strLen = str.length(); 5302 final int pads = size - strLen; 5303 if (pads <= 0) { 5304 return str; // returns original String when possible 5305 } 5306 if (padLen == 1 && pads <= PAD_LIMIT) { 5307 return rightPad(str, size, padStr.charAt(0)); 5308 } 5309 5310 if (pads == padLen) { 5311 return str.concat(padStr); 5312 } else if (pads < padLen) { 5313 return str.concat(padStr.substring(0, pads)); 5314 } else { 5315 final char[] padding = new char[pads]; 5316 final char[] padChars = padStr.toCharArray(); 5317 for (int i = 0; i < pads; i++) { 5318 padding[i] = padChars[i % padLen]; 5319 } 5320 return str.concat(new String(padding)); 5321 } 5322 } 5323 5324 /** 5325 * <p>Left pad a String with spaces (' ').</p> 5326 * 5327 * <p>The String is padded to the size of {@code size}.</p> 5328 * 5329 * <pre> 5330 * StringUtils.leftPad(null, *) = null 5331 * StringUtils.leftPad("", 3) = " " 5332 * StringUtils.leftPad("bat", 3) = "bat" 5333 * StringUtils.leftPad("bat", 5) = " bat" 5334 * StringUtils.leftPad("bat", 1) = "bat" 5335 * StringUtils.leftPad("bat", -1) = "bat" 5336 * </pre> 5337 * 5338 * @param str the String to pad out, may be null 5339 * @param size the size to pad to 5340 * @return left padded String or original String if no padding is necessary, 5341 * {@code null} if null String input 5342 */ 5343 public static String leftPad(final String str, final int size) { 5344 return leftPad(str, size, ' '); 5345 } 5346 5347 /** 5348 * <p>Left pad a String with a specified character.</p> 5349 * 5350 * <p>Pad to a size of {@code size}.</p> 5351 * 5352 * <pre> 5353 * StringUtils.leftPad(null, *, *) = null 5354 * StringUtils.leftPad("", 3, 'z') = "zzz" 5355 * StringUtils.leftPad("bat", 3, 'z') = "bat" 5356 * StringUtils.leftPad("bat", 5, 'z') = "zzbat" 5357 * StringUtils.leftPad("bat", 1, 'z') = "bat" 5358 * StringUtils.leftPad("bat", -1, 'z') = "bat" 5359 * </pre> 5360 * 5361 * @param str the String to pad out, may be null 5362 * @param size the size to pad to 5363 * @param padChar the character to pad with 5364 * @return left padded String or original String if no padding is necessary, 5365 * {@code null} if null String input 5366 * @since 2.0 5367 */ 5368 public static String leftPad(final String str, final int size, final char padChar) { 5369 if (str == null) { 5370 return null; 5371 } 5372 final int pads = size - str.length(); 5373 if (pads <= 0) { 5374 return str; // returns original String when possible 5375 } 5376 if (pads > PAD_LIMIT) { 5377 return leftPad(str, size, String.valueOf(padChar)); 5378 } 5379 return repeat(padChar, pads).concat(str); 5380 } 5381 5382 /** 5383 * <p>Left pad a String with a specified String.</p> 5384 * 5385 * <p>Pad to a size of {@code size}.</p> 5386 * 5387 * <pre> 5388 * StringUtils.leftPad(null, *, *) = null 5389 * StringUtils.leftPad("", 3, "z") = "zzz" 5390 * StringUtils.leftPad("bat", 3, "yz") = "bat" 5391 * StringUtils.leftPad("bat", 5, "yz") = "yzbat" 5392 * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat" 5393 * StringUtils.leftPad("bat", 1, "yz") = "bat" 5394 * StringUtils.leftPad("bat", -1, "yz") = "bat" 5395 * StringUtils.leftPad("bat", 5, null) = " bat" 5396 * StringUtils.leftPad("bat", 5, "") = " bat" 5397 * </pre> 5398 * 5399 * @param str the String to pad out, may be null 5400 * @param size the size to pad to 5401 * @param padStr the String to pad with, null or empty treated as single space 5402 * @return left padded String or original String if no padding is necessary, 5403 * {@code null} if null String input 5404 */ 5405 public static String leftPad(final String str, final int size, String padStr) { 5406 if (str == null) { 5407 return null; 5408 } 5409 if (isEmpty(padStr)) { 5410 padStr = SPACE; 5411 } 5412 final int padLen = padStr.length(); 5413 final int strLen = str.length(); 5414 final int pads = size - strLen; 5415 if (pads <= 0) { 5416 return str; // returns original String when possible 5417 } 5418 if (padLen == 1 && pads <= PAD_LIMIT) { 5419 return leftPad(str, size, padStr.charAt(0)); 5420 } 5421 5422 if (pads == padLen) { 5423 return padStr.concat(str); 5424 } else if (pads < padLen) { 5425 return padStr.substring(0, pads).concat(str); 5426 } else { 5427 final char[] padding = new char[pads]; 5428 final char[] padChars = padStr.toCharArray(); 5429 for (int i = 0; i < pads; i++) { 5430 padding[i] = padChars[i % padLen]; 5431 } 5432 return new String(padding).concat(str); 5433 } 5434 } 5435 5436 /** 5437 * Gets a CharSequence length or {@code 0} if the CharSequence is 5438 * {@code null}. 5439 * 5440 * @param cs 5441 * a CharSequence or {@code null} 5442 * @return CharSequence length or {@code 0} if the CharSequence is 5443 * {@code null}. 5444 * @since 2.4 5445 * @since 3.0 Changed signature from length(String) to length(CharSequence) 5446 */ 5447 public static int length(final CharSequence cs) { 5448 return cs == null ? 0 : cs.length(); 5449 } 5450 5451 // Centering 5452 //----------------------------------------------------------------------- 5453 /** 5454 * <p>Centers a String in a larger String of size {@code size} 5455 * using the space character (' ').<p> 5456 * 5457 * <p>If the size is less than the String length, the String is returned. 5458 * A {@code null} String returns {@code null}. 5459 * A negative size is treated as zero.</p> 5460 * 5461 * <p>Equivalent to {@code center(str, size, " ")}.</p> 5462 * 5463 * <pre> 5464 * StringUtils.center(null, *) = null 5465 * StringUtils.center("", 4) = " " 5466 * StringUtils.center("ab", -1) = "ab" 5467 * StringUtils.center("ab", 4) = " ab " 5468 * StringUtils.center("abcd", 2) = "abcd" 5469 * StringUtils.center("a", 4) = " a " 5470 * </pre> 5471 * 5472 * @param str the String to center, may be null 5473 * @param size the int size of new String, negative treated as zero 5474 * @return centered String, {@code null} if null String input 5475 */ 5476 public static String center(final String str, final int size) { 5477 return center(str, size, ' '); 5478 } 5479 5480 /** 5481 * <p>Centers a String in a larger String of size {@code size}. 5482 * Uses a supplied character as the value to pad the String with.</p> 5483 * 5484 * <p>If the size is less than the String length, the String is returned. 5485 * A {@code null} String returns {@code null}. 5486 * A negative size is treated as zero.</p> 5487 * 5488 * <pre> 5489 * StringUtils.center(null, *, *) = null 5490 * StringUtils.center("", 4, ' ') = " " 5491 * StringUtils.center("ab", -1, ' ') = "ab" 5492 * StringUtils.center("ab", 4, ' ') = " ab " 5493 * StringUtils.center("abcd", 2, ' ') = "abcd" 5494 * StringUtils.center("a", 4, ' ') = " a " 5495 * StringUtils.center("a", 4, 'y') = "yayy" 5496 * </pre> 5497 * 5498 * @param str the String to center, may be null 5499 * @param size the int size of new String, negative treated as zero 5500 * @param padChar the character to pad the new String with 5501 * @return centered String, {@code null} if null String input 5502 * @since 2.0 5503 */ 5504 public static String center(String str, final int size, final char padChar) { 5505 if (str == null || size <= 0) { 5506 return str; 5507 } 5508 final int strLen = str.length(); 5509 final int pads = size - strLen; 5510 if (pads <= 0) { 5511 return str; 5512 } 5513 str = leftPad(str, strLen + pads / 2, padChar); 5514 str = rightPad(str, size, padChar); 5515 return str; 5516 } 5517 5518 /** 5519 * <p>Centers a String in a larger String of size {@code size}. 5520 * Uses a supplied String as the value to pad the String with.</p> 5521 * 5522 * <p>If the size is less than the String length, the String is returned. 5523 * A {@code null} String returns {@code null}. 5524 * A negative size is treated as zero.</p> 5525 * 5526 * <pre> 5527 * StringUtils.center(null, *, *) = null 5528 * StringUtils.center("", 4, " ") = " " 5529 * StringUtils.center("ab", -1, " ") = "ab" 5530 * StringUtils.center("ab", 4, " ") = " ab " 5531 * StringUtils.center("abcd", 2, " ") = "abcd" 5532 * StringUtils.center("a", 4, " ") = " a " 5533 * StringUtils.center("a", 4, "yz") = "yayz" 5534 * StringUtils.center("abc", 7, null) = " abc " 5535 * StringUtils.center("abc", 7, "") = " abc " 5536 * </pre> 5537 * 5538 * @param str the String to center, may be null 5539 * @param size the int size of new String, negative treated as zero 5540 * @param padStr the String to pad the new String with, must not be null or empty 5541 * @return centered String, {@code null} if null String input 5542 * @throws IllegalArgumentException if padStr is {@code null} or empty 5543 */ 5544 public static String center(String str, final int size, String padStr) { 5545 if (str == null || size <= 0) { 5546 return str; 5547 } 5548 if (isEmpty(padStr)) { 5549 padStr = SPACE; 5550 } 5551 final int strLen = str.length(); 5552 final int pads = size - strLen; 5553 if (pads <= 0) { 5554 return str; 5555 } 5556 str = leftPad(str, strLen + pads / 2, padStr); 5557 str = rightPad(str, size, padStr); 5558 return str; 5559 } 5560 5561 // Case conversion 5562 //----------------------------------------------------------------------- 5563 /** 5564 * <p>Converts a String to upper case as per {@link String#toUpperCase()}.</p> 5565 * 5566 * <p>A {@code null} input String returns {@code null}.</p> 5567 * 5568 * <pre> 5569 * StringUtils.upperCase(null) = null 5570 * StringUtils.upperCase("") = "" 5571 * StringUtils.upperCase("aBc") = "ABC" 5572 * </pre> 5573 * 5574 * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()}, 5575 * the result of this method is affected by the current locale. 5576 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} 5577 * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p> 5578 * 5579 * @param str the String to upper case, may be null 5580 * @return the upper cased String, {@code null} if null String input 5581 */ 5582 public static String upperCase(final String str) { 5583 if (str == null) { 5584 return null; 5585 } 5586 return str.toUpperCase(); 5587 } 5588 5589 /** 5590 * <p>Converts a String to upper case as per {@link String#toUpperCase(Locale)}.</p> 5591 * 5592 * <p>A {@code null} input String returns {@code null}.</p> 5593 * 5594 * <pre> 5595 * StringUtils.upperCase(null, Locale.ENGLISH) = null 5596 * StringUtils.upperCase("", Locale.ENGLISH) = "" 5597 * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC" 5598 * </pre> 5599 * 5600 * @param str the String to upper case, may be null 5601 * @param locale the locale that defines the case transformation rules, must not be null 5602 * @return the upper cased String, {@code null} if null String input 5603 * @since 2.5 5604 */ 5605 public static String upperCase(final String str, final Locale locale) { 5606 if (str == null) { 5607 return null; 5608 } 5609 return str.toUpperCase(locale); 5610 } 5611 5612 /** 5613 * <p>Converts a String to lower case as per {@link String#toLowerCase()}.</p> 5614 * 5615 * <p>A {@code null} input String returns {@code null}.</p> 5616 * 5617 * <pre> 5618 * StringUtils.lowerCase(null) = null 5619 * StringUtils.lowerCase("") = "" 5620 * StringUtils.lowerCase("aBc") = "abc" 5621 * </pre> 5622 * 5623 * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()}, 5624 * the result of this method is affected by the current locale. 5625 * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} 5626 * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p> 5627 * 5628 * @param str the String to lower case, may be null 5629 * @return the lower cased String, {@code null} if null String input 5630 */ 5631 public static String lowerCase(final String str) { 5632 if (str == null) { 5633 return null; 5634 } 5635 return str.toLowerCase(); 5636 } 5637 5638 /** 5639 * <p>Converts a String to lower case as per {@link String#toLowerCase(Locale)}.</p> 5640 * 5641 * <p>A {@code null} input String returns {@code null}.</p> 5642 * 5643 * <pre> 5644 * StringUtils.lowerCase(null, Locale.ENGLISH) = null 5645 * StringUtils.lowerCase("", Locale.ENGLISH) = "" 5646 * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc" 5647 * </pre> 5648 * 5649 * @param str the String to lower case, may be null 5650 * @param locale the locale that defines the case transformation rules, must not be null 5651 * @return the lower cased String, {@code null} if null String input 5652 * @since 2.5 5653 */ 5654 public static String lowerCase(final String str, final Locale locale) { 5655 if (str == null) { 5656 return null; 5657 } 5658 return str.toLowerCase(locale); 5659 } 5660 5661 /** 5662 * <p>Capitalizes a String changing the first letter to title case as 5663 * per {@link Character#toTitleCase(char)}. No other letters are changed.</p> 5664 * 5665 * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#capitalize(String)}. 5666 * A {@code null} input String returns {@code null}.</p> 5667 * 5668 * <pre> 5669 * StringUtils.capitalize(null) = null 5670 * StringUtils.capitalize("") = "" 5671 * StringUtils.capitalize("cat") = "Cat" 5672 * StringUtils.capitalize("cAt") = "CAt" 5673 * </pre> 5674 * 5675 * @param str the String to capitalize, may be null 5676 * @return the capitalized String, {@code null} if null String input 5677 * @see org.apache.commons.lang3.text.WordUtils#capitalize(String) 5678 * @see #uncapitalize(String) 5679 * @since 2.0 5680 */ 5681 public static String capitalize(final String str) { 5682 int strLen; 5683 if (str == null || (strLen = str.length()) == 0) { 5684 return str; 5685 } 5686 5687 char firstChar = str.charAt(0); 5688 if (Character.isTitleCase(firstChar)) { 5689 // already capitalized 5690 return str; 5691 } 5692 5693 return new StringBuilder(strLen) 5694 .append(Character.toTitleCase(firstChar)) 5695 .append(str.substring(1)) 5696 .toString(); 5697 } 5698 5699 /** 5700 * <p>Uncapitalizes a String changing the first letter to title case as 5701 * per {@link Character#toLowerCase(char)}. No other letters are changed.</p> 5702 * 5703 * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#uncapitalize(String)}. 5704 * A {@code null} input String returns {@code null}.</p> 5705 * 5706 * <pre> 5707 * StringUtils.uncapitalize(null) = null 5708 * StringUtils.uncapitalize("") = "" 5709 * StringUtils.uncapitalize("Cat") = "cat" 5710 * StringUtils.uncapitalize("CAT") = "cAT" 5711 * </pre> 5712 * 5713 * @param str the String to uncapitalize, may be null 5714 * @return the uncapitalized String, {@code null} if null String input 5715 * @see org.apache.commons.lang3.text.WordUtils#uncapitalize(String) 5716 * @see #capitalize(String) 5717 * @since 2.0 5718 */ 5719 public static String uncapitalize(final String str) { 5720 int strLen; 5721 if (str == null || (strLen = str.length()) == 0) { 5722 return str; 5723 } 5724 5725 char firstChar = str.charAt(0); 5726 if (Character.isLowerCase(firstChar)) { 5727 // already uncapitalized 5728 return str; 5729 } 5730 5731 return new StringBuilder(strLen) 5732 .append(Character.toLowerCase(firstChar)) 5733 .append(str.substring(1)) 5734 .toString(); 5735 } 5736 5737 /** 5738 * <p>Swaps the case of a String changing upper and title case to 5739 * lower case, and lower case to upper case.</p> 5740 * 5741 * <ul> 5742 * <li>Upper case character converts to Lower case</li> 5743 * <li>Title case character converts to Lower case</li> 5744 * <li>Lower case character converts to Upper case</li> 5745 * </ul> 5746 * 5747 * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#swapCase(String)}. 5748 * A {@code null} input String returns {@code null}.</p> 5749 * 5750 * <pre> 5751 * StringUtils.swapCase(null) = null 5752 * StringUtils.swapCase("") = "" 5753 * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" 5754 * </pre> 5755 * 5756 * <p>NOTE: This method changed in Lang version 2.0. 5757 * It no longer performs a word based algorithm. 5758 * If you only use ASCII, you will notice no change. 5759 * That functionality is available in org.apache.commons.lang3.text.WordUtils.</p> 5760 * 5761 * @param str the String to swap case, may be null 5762 * @return the changed String, {@code null} if null String input 5763 */ 5764 public static String swapCase(final String str) { 5765 if (StringUtils.isEmpty(str)) { 5766 return str; 5767 } 5768 5769 final char[] buffer = str.toCharArray(); 5770 5771 for (int i = 0; i < buffer.length; i++) { 5772 final char ch = buffer[i]; 5773 if (Character.isUpperCase(ch)) { 5774 buffer[i] = Character.toLowerCase(ch); 5775 } else if (Character.isTitleCase(ch)) { 5776 buffer[i] = Character.toLowerCase(ch); 5777 } else if (Character.isLowerCase(ch)) { 5778 buffer[i] = Character.toUpperCase(ch); 5779 } 5780 } 5781 return new String(buffer); 5782 } 5783 5784 // Count matches 5785 //----------------------------------------------------------------------- 5786 /** 5787 * <p>Counts how many times the substring appears in the larger string.</p> 5788 * 5789 * <p>A {@code null} or empty ("") String input returns {@code 0}.</p> 5790 * 5791 * <pre> 5792 * StringUtils.countMatches(null, *) = 0 5793 * StringUtils.countMatches("", *) = 0 5794 * StringUtils.countMatches("abba", null) = 0 5795 * StringUtils.countMatches("abba", "") = 0 5796 * StringUtils.countMatches("abba", "a") = 2 5797 * StringUtils.countMatches("abba", "ab") = 1 5798 * StringUtils.countMatches("abba", "xxx") = 0 5799 * </pre> 5800 * 5801 * @param str the CharSequence to check, may be null 5802 * @param sub the substring to count, may be null 5803 * @return the number of occurrences, 0 if either CharSequence is {@code null} 5804 * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence) 5805 */ 5806 public static int countMatches(final CharSequence str, final CharSequence sub) { 5807 if (isEmpty(str) || isEmpty(sub)) { 5808 return 0; 5809 } 5810 int count = 0; 5811 int idx = 0; 5812 while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) { 5813 count++; 5814 idx += sub.length(); 5815 } 5816 return count; 5817 } 5818 5819 // Character Tests 5820 //----------------------------------------------------------------------- 5821 /** 5822 * <p>Checks if the CharSequence contains only Unicode letters.</p> 5823 * 5824 * <p>{@code null} will return {@code false}. 5825 * An empty CharSequence (length()=0) will return {@code false}.</p> 5826 * 5827 * <pre> 5828 * StringUtils.isAlpha(null) = false 5829 * StringUtils.isAlpha("") = false 5830 * StringUtils.isAlpha(" ") = false 5831 * StringUtils.isAlpha("abc") = true 5832 * StringUtils.isAlpha("ab2c") = false 5833 * StringUtils.isAlpha("ab-c") = false 5834 * </pre> 5835 * 5836 * @param cs the CharSequence to check, may be null 5837 * @return {@code true} if only contains letters, and is non-null 5838 * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence) 5839 * @since 3.0 Changed "" to return false and not true 5840 */ 5841 public static boolean isAlpha(final CharSequence cs) { 5842 if (isEmpty(cs)) { 5843 return false; 5844 } 5845 final int sz = cs.length(); 5846 for (int i = 0; i < sz; i++) { 5847 if (Character.isLetter(cs.charAt(i)) == false) { 5848 return false; 5849 } 5850 } 5851 return true; 5852 } 5853 5854 /** 5855 * <p>Checks if the CharSequence contains only Unicode letters and 5856 * space (' ').</p> 5857 * 5858 * <p>{@code null} will return {@code false} 5859 * An empty CharSequence (length()=0) will return {@code true}.</p> 5860 * 5861 * <pre> 5862 * StringUtils.isAlphaSpace(null) = false 5863 * StringUtils.isAlphaSpace("") = true 5864 * StringUtils.isAlphaSpace(" ") = true 5865 * StringUtils.isAlphaSpace("abc") = true 5866 * StringUtils.isAlphaSpace("ab c") = true 5867 * StringUtils.isAlphaSpace("ab2c") = false 5868 * StringUtils.isAlphaSpace("ab-c") = false 5869 * </pre> 5870 * 5871 * @param cs the CharSequence to check, may be null 5872 * @return {@code true} if only contains letters and space, 5873 * and is non-null 5874 * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence) 5875 */ 5876 public static boolean isAlphaSpace(final CharSequence cs) { 5877 if (cs == null) { 5878 return false; 5879 } 5880 final int sz = cs.length(); 5881 for (int i = 0; i < sz; i++) { 5882 if (Character.isLetter(cs.charAt(i)) == false && cs.charAt(i) != ' ') { 5883 return false; 5884 } 5885 } 5886 return true; 5887 } 5888 5889 /** 5890 * <p>Checks if the CharSequence contains only Unicode letters or digits.</p> 5891 * 5892 * <p>{@code null} will return {@code false}. 5893 * An empty CharSequence (length()=0) will return {@code false}.</p> 5894 * 5895 * <pre> 5896 * StringUtils.isAlphanumeric(null) = false 5897 * StringUtils.isAlphanumeric("") = false 5898 * StringUtils.isAlphanumeric(" ") = false 5899 * StringUtils.isAlphanumeric("abc") = true 5900 * StringUtils.isAlphanumeric("ab c") = false 5901 * StringUtils.isAlphanumeric("ab2c") = true 5902 * StringUtils.isAlphanumeric("ab-c") = false 5903 * </pre> 5904 * 5905 * @param cs the CharSequence to check, may be null 5906 * @return {@code true} if only contains letters or digits, 5907 * and is non-null 5908 * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence) 5909 * @since 3.0 Changed "" to return false and not true 5910 */ 5911 public static boolean isAlphanumeric(final CharSequence cs) { 5912 if (isEmpty(cs)) { 5913 return false; 5914 } 5915 final int sz = cs.length(); 5916 for (int i = 0; i < sz; i++) { 5917 if (Character.isLetterOrDigit(cs.charAt(i)) == false) { 5918 return false; 5919 } 5920 } 5921 return true; 5922 } 5923 5924 /** 5925 * <p>Checks if the CharSequence contains only Unicode letters, digits 5926 * or space ({@code ' '}).</p> 5927 * 5928 * <p>{@code null} will return {@code false}. 5929 * An empty CharSequence (length()=0) will return {@code true}.</p> 5930 * 5931 * <pre> 5932 * StringUtils.isAlphanumericSpace(null) = false 5933 * StringUtils.isAlphanumericSpace("") = true 5934 * StringUtils.isAlphanumericSpace(" ") = true 5935 * StringUtils.isAlphanumericSpace("abc") = true 5936 * StringUtils.isAlphanumericSpace("ab c") = true 5937 * StringUtils.isAlphanumericSpace("ab2c") = true 5938 * StringUtils.isAlphanumericSpace("ab-c") = false 5939 * </pre> 5940 * 5941 * @param cs the CharSequence to check, may be null 5942 * @return {@code true} if only contains letters, digits or space, 5943 * and is non-null 5944 * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence) 5945 */ 5946 public static boolean isAlphanumericSpace(final CharSequence cs) { 5947 if (cs == null) { 5948 return false; 5949 } 5950 final int sz = cs.length(); 5951 for (int i = 0; i < sz; i++) { 5952 if (Character.isLetterOrDigit(cs.charAt(i)) == false && cs.charAt(i) != ' ') { 5953 return false; 5954 } 5955 } 5956 return true; 5957 } 5958 5959 /** 5960 * <p>Checks if the CharSequence contains only ASCII printable characters.</p> 5961 * 5962 * <p>{@code null} will return {@code false}. 5963 * An empty CharSequence (length()=0) will return {@code true}.</p> 5964 * 5965 * <pre> 5966 * StringUtils.isAsciiPrintable(null) = false 5967 * StringUtils.isAsciiPrintable("") = true 5968 * StringUtils.isAsciiPrintable(" ") = true 5969 * StringUtils.isAsciiPrintable("Ceki") = true 5970 * StringUtils.isAsciiPrintable("ab2c") = true 5971 * StringUtils.isAsciiPrintable("!ab-c~") = true 5972 * StringUtils.isAsciiPrintable("\u0020") = true 5973 * StringUtils.isAsciiPrintable("\u0021") = true 5974 * StringUtils.isAsciiPrintable("\u007e") = true 5975 * StringUtils.isAsciiPrintable("\u007f") = false 5976 * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false 5977 * </pre> 5978 * 5979 * @param cs the CharSequence to check, may be null 5980 * @return {@code true} if every character is in the range 5981 * 32 thru 126 5982 * @since 2.1 5983 * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence) 5984 */ 5985 public static boolean isAsciiPrintable(final CharSequence cs) { 5986 if (cs == null) { 5987 return false; 5988 } 5989 final int sz = cs.length(); 5990 for (int i = 0; i < sz; i++) { 5991 if (CharUtils.isAsciiPrintable(cs.charAt(i)) == false) { 5992 return false; 5993 } 5994 } 5995 return true; 5996 } 5997 5998 /** 5999 * <p>Checks if the CharSequence contains only Unicode digits. 6000 * A decimal point is not a Unicode digit and returns false.</p> 6001 * 6002 * <p>{@code null} will return {@code false}. 6003 * An empty CharSequence (length()=0) will return {@code false}.</p> 6004 * 6005 * <p>Note that the method does not allow for a leading sign, either positive or negative. 6006 * Also, if a String passes the numeric test, it may still generate a NumberFormatException 6007 * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range 6008 * for int or long respectively.</p> 6009 * 6010 * <pre> 6011 * StringUtils.isNumeric(null) = false 6012 * StringUtils.isNumeric("") = false 6013 * StringUtils.isNumeric(" ") = false 6014 * StringUtils.isNumeric("123") = true 6015 * StringUtils.isNumeric("12 3") = false 6016 * StringUtils.isNumeric("ab2c") = false 6017 * StringUtils.isNumeric("12-3") = false 6018 * StringUtils.isNumeric("12.3") = false 6019 * StringUtils.isNumeric("-123") = false 6020 * StringUtils.isNumeric("+123") = false 6021 * </pre> 6022 * 6023 * @param cs the CharSequence to check, may be null 6024 * @return {@code true} if only contains digits, and is non-null 6025 * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence) 6026 * @since 3.0 Changed "" to return false and not true 6027 */ 6028 public static boolean isNumeric(final CharSequence cs) { 6029 if (isEmpty(cs)) { 6030 return false; 6031 } 6032 final int sz = cs.length(); 6033 for (int i = 0; i < sz; i++) { 6034 if (Character.isDigit(cs.charAt(i)) == false) { 6035 return false; 6036 } 6037 } 6038 return true; 6039 } 6040 6041 /** 6042 * <p>Checks if the CharSequence contains only Unicode digits or space 6043 * ({@code ' '}). 6044 * A decimal point is not a Unicode digit and returns false.</p> 6045 * 6046 * <p>{@code null} will return {@code false}. 6047 * An empty CharSequence (length()=0) will return {@code true}.</p> 6048 * 6049 * <pre> 6050 * StringUtils.isNumericSpace(null) = false 6051 * StringUtils.isNumericSpace("") = true 6052 * StringUtils.isNumericSpace(" ") = true 6053 * StringUtils.isNumericSpace("123") = true 6054 * StringUtils.isNumericSpace("12 3") = true 6055 * StringUtils.isNumericSpace("ab2c") = false 6056 * StringUtils.isNumericSpace("12-3") = false 6057 * StringUtils.isNumericSpace("12.3") = false 6058 * </pre> 6059 * 6060 * @param cs the CharSequence to check, may be null 6061 * @return {@code true} if only contains digits or space, 6062 * and is non-null 6063 * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence) 6064 */ 6065 public static boolean isNumericSpace(final CharSequence cs) { 6066 if (cs == null) { 6067 return false; 6068 } 6069 final int sz = cs.length(); 6070 for (int i = 0; i < sz; i++) { 6071 if (Character.isDigit(cs.charAt(i)) == false && cs.charAt(i) != ' ') { 6072 return false; 6073 } 6074 } 6075 return true; 6076 } 6077 6078 /** 6079 * <p>Checks if the CharSequence contains only whitespace.</p> 6080 * 6081 * <p>{@code null} will return {@code false}. 6082 * An empty CharSequence (length()=0) will return {@code true}.</p> 6083 * 6084 * <pre> 6085 * StringUtils.isWhitespace(null) = false 6086 * StringUtils.isWhitespace("") = true 6087 * StringUtils.isWhitespace(" ") = true 6088 * StringUtils.isWhitespace("abc") = false 6089 * StringUtils.isWhitespace("ab2c") = false 6090 * StringUtils.isWhitespace("ab-c") = false 6091 * </pre> 6092 * 6093 * @param cs the CharSequence to check, may be null 6094 * @return {@code true} if only contains whitespace, and is non-null 6095 * @since 2.0 6096 * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence) 6097 */ 6098 public static boolean isWhitespace(final CharSequence cs) { 6099 if (cs == null) { 6100 return false; 6101 } 6102 final int sz = cs.length(); 6103 for (int i = 0; i < sz; i++) { 6104 if (Character.isWhitespace(cs.charAt(i)) == false) { 6105 return false; 6106 } 6107 } 6108 return true; 6109 } 6110 6111 /** 6112 * <p>Checks if the CharSequence contains only lowercase characters.</p> 6113 * 6114 * <p>{@code null} will return {@code false}. 6115 * An empty CharSequence (length()=0) will return {@code false}.</p> 6116 * 6117 * <pre> 6118 * StringUtils.isAllLowerCase(null) = false 6119 * StringUtils.isAllLowerCase("") = false 6120 * StringUtils.isAllLowerCase(" ") = false 6121 * StringUtils.isAllLowerCase("abc") = true 6122 * StringUtils.isAllLowerCase("abC") = false 6123 * </pre> 6124 * 6125 * @param cs the CharSequence to check, may be null 6126 * @return {@code true} if only contains lowercase characters, and is non-null 6127 * @since 2.5 6128 * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence) 6129 */ 6130 public static boolean isAllLowerCase(final CharSequence cs) { 6131 if (cs == null || isEmpty(cs)) { 6132 return false; 6133 } 6134 final int sz = cs.length(); 6135 for (int i = 0; i < sz; i++) { 6136 if (Character.isLowerCase(cs.charAt(i)) == false) { 6137 return false; 6138 } 6139 } 6140 return true; 6141 } 6142 6143 /** 6144 * <p>Checks if the CharSequence contains only uppercase characters.</p> 6145 * 6146 * <p>{@code null} will return {@code false}. 6147 * An empty String (length()=0) will return {@code false}.</p> 6148 * 6149 * <pre> 6150 * StringUtils.isAllUpperCase(null) = false 6151 * StringUtils.isAllUpperCase("") = false 6152 * StringUtils.isAllUpperCase(" ") = false 6153 * StringUtils.isAllUpperCase("ABC") = true 6154 * StringUtils.isAllUpperCase("aBC") = false 6155 * </pre> 6156 * 6157 * @param cs the CharSequence to check, may be null 6158 * @return {@code true} if only contains uppercase characters, and is non-null 6159 * @since 2.5 6160 * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence) 6161 */ 6162 public static boolean isAllUpperCase(final CharSequence cs) { 6163 if (cs == null || isEmpty(cs)) { 6164 return false; 6165 } 6166 final int sz = cs.length(); 6167 for (int i = 0; i < sz; i++) { 6168 if (Character.isUpperCase(cs.charAt(i)) == false) { 6169 return false; 6170 } 6171 } 6172 return true; 6173 } 6174 6175 // Defaults 6176 //----------------------------------------------------------------------- 6177 /** 6178 * <p>Returns either the passed in String, 6179 * or if the String is {@code null}, an empty String ("").</p> 6180 * 6181 * <pre> 6182 * StringUtils.defaultString(null) = "" 6183 * StringUtils.defaultString("") = "" 6184 * StringUtils.defaultString("bat") = "bat" 6185 * </pre> 6186 * 6187 * @see ObjectUtils#toString(Object) 6188 * @see String#valueOf(Object) 6189 * @param str the String to check, may be null 6190 * @return the passed in String, or the empty String if it 6191 * was {@code null} 6192 */ 6193 public static String defaultString(final String str) { 6194 return str == null ? EMPTY : str; 6195 } 6196 6197 /** 6198 * <p>Returns either the passed in String, or if the String is 6199 * {@code null}, the value of {@code defaultStr}.</p> 6200 * 6201 * <pre> 6202 * StringUtils.defaultString(null, "NULL") = "NULL" 6203 * StringUtils.defaultString("", "NULL") = "" 6204 * StringUtils.defaultString("bat", "NULL") = "bat" 6205 * </pre> 6206 * 6207 * @see ObjectUtils#toString(Object,String) 6208 * @see String#valueOf(Object) 6209 * @param str the String to check, may be null 6210 * @param defaultStr the default String to return 6211 * if the input is {@code null}, may be null 6212 * @return the passed in String, or the default if it was {@code null} 6213 */ 6214 public static String defaultString(final String str, final String defaultStr) { 6215 return str == null ? defaultStr : str; 6216 } 6217 6218 /** 6219 * <p>Returns either the passed in CharSequence, or if the CharSequence is 6220 * whitespace, empty ("") or {@code null}, the value of {@code defaultStr}.</p> 6221 * 6222 * <pre> 6223 * StringUtils.defaultIfBlank(null, "NULL") = "NULL" 6224 * StringUtils.defaultIfBlank("", "NULL") = "NULL" 6225 * StringUtils.defaultIfBlank(" ", "NULL") = "NULL" 6226 * StringUtils.defaultIfBlank("bat", "NULL") = "bat" 6227 * StringUtils.defaultIfBlank("", null) = null 6228 * </pre> 6229 * @param <T> the specific kind of CharSequence 6230 * @param str the CharSequence to check, may be null 6231 * @param defaultStr the default CharSequence to return 6232 * if the input is whitespace, empty ("") or {@code null}, may be null 6233 * @return the passed in CharSequence, or the default 6234 * @see StringUtils#defaultString(String, String) 6235 */ 6236 public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) { 6237 return StringUtils.isBlank(str) ? defaultStr : str; 6238 } 6239 6240 /** 6241 * <p>Returns either the passed in CharSequence, or if the CharSequence is 6242 * empty or {@code null}, the value of {@code defaultStr}.</p> 6243 * 6244 * <pre> 6245 * StringUtils.defaultIfEmpty(null, "NULL") = "NULL" 6246 * StringUtils.defaultIfEmpty("", "NULL") = "NULL" 6247 * StringUtils.defaultIfEmpty(" ", "NULL") = " " 6248 * StringUtils.defaultIfEmpty("bat", "NULL") = "bat" 6249 * StringUtils.defaultIfEmpty("", null) = null 6250 * </pre> 6251 * @param <T> the specific kind of CharSequence 6252 * @param str the CharSequence to check, may be null 6253 * @param defaultStr the default CharSequence to return 6254 * if the input is empty ("") or {@code null}, may be null 6255 * @return the passed in CharSequence, or the default 6256 * @see StringUtils#defaultString(String, String) 6257 */ 6258 public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) { 6259 return StringUtils.isEmpty(str) ? defaultStr : str; 6260 } 6261 6262 // Reversing 6263 //----------------------------------------------------------------------- 6264 /** 6265 * <p>Reverses a String as per {@link StringBuilder#reverse()}.</p> 6266 * 6267 * <p>A {@code null} String returns {@code null}.</p> 6268 * 6269 * <pre> 6270 * StringUtils.reverse(null) = null 6271 * StringUtils.reverse("") = "" 6272 * StringUtils.reverse("bat") = "tab" 6273 * </pre> 6274 * 6275 * @param str the String to reverse, may be null 6276 * @return the reversed String, {@code null} if null String input 6277 */ 6278 public static String reverse(final String str) { 6279 if (str == null) { 6280 return null; 6281 } 6282 return new StringBuilder(str).reverse().toString(); 6283 } 6284 6285 /** 6286 * <p>Reverses a String that is delimited by a specific character.</p> 6287 * 6288 * <p>The Strings between the delimiters are not reversed. 6289 * Thus java.lang.String becomes String.lang.java (if the delimiter 6290 * is {@code '.'}).</p> 6291 * 6292 * <pre> 6293 * StringUtils.reverseDelimited(null, *) = null 6294 * StringUtils.reverseDelimited("", *) = "" 6295 * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c" 6296 * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a" 6297 * </pre> 6298 * 6299 * @param str the String to reverse, may be null 6300 * @param separatorChar the separator character to use 6301 * @return the reversed String, {@code null} if null String input 6302 * @since 2.0 6303 */ 6304 public static String reverseDelimited(final String str, final char separatorChar) { 6305 if (str == null) { 6306 return null; 6307 } 6308 // could implement manually, but simple way is to reuse other, 6309 // probably slower, methods. 6310 final String[] strs = split(str, separatorChar); 6311 ArrayUtils.reverse(strs); 6312 return join(strs, separatorChar); 6313 } 6314 6315 // Abbreviating 6316 //----------------------------------------------------------------------- 6317 /** 6318 * <p>Abbreviates a String using ellipses. This will turn 6319 * "Now is the time for all good men" into "Now is the time for..."</p> 6320 * 6321 * <p>Specifically: 6322 * <ul> 6323 * <li>If {@code str} is less than {@code maxWidth} characters 6324 * long, return it.</li> 6325 * <li>Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.</li> 6326 * <li>If {@code maxWidth} is less than {@code 4}, throw an 6327 * {@code IllegalArgumentException}.</li> 6328 * <li>In no case will it return a String of length greater than 6329 * {@code maxWidth}.</li> 6330 * </ul> 6331 * </p> 6332 * 6333 * <pre> 6334 * StringUtils.abbreviate(null, *) = null 6335 * StringUtils.abbreviate("", 4) = "" 6336 * StringUtils.abbreviate("abcdefg", 6) = "abc..." 6337 * StringUtils.abbreviate("abcdefg", 7) = "abcdefg" 6338 * StringUtils.abbreviate("abcdefg", 8) = "abcdefg" 6339 * StringUtils.abbreviate("abcdefg", 4) = "a..." 6340 * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException 6341 * </pre> 6342 * 6343 * @param str the String to check, may be null 6344 * @param maxWidth maximum length of result String, must be at least 4 6345 * @return abbreviated String, {@code null} if null String input 6346 * @throws IllegalArgumentException if the width is too small 6347 * @since 2.0 6348 */ 6349 public static String abbreviate(final String str, final int maxWidth) { 6350 return abbreviate(str, 0, maxWidth); 6351 } 6352 6353 /** 6354 * <p>Abbreviates a String using ellipses. This will turn 6355 * "Now is the time for all good men" into "...is the time for..."</p> 6356 * 6357 * <p>Works like {@code abbreviate(String, int)}, but allows you to specify 6358 * a "left edge" offset. Note that this left edge is not necessarily going to 6359 * be the leftmost character in the result, or the first character following the 6360 * ellipses, but it will appear somewhere in the result. 6361 * 6362 * <p>In no case will it return a String of length greater than 6363 * {@code maxWidth}.</p> 6364 * 6365 * <pre> 6366 * StringUtils.abbreviate(null, *, *) = null 6367 * StringUtils.abbreviate("", 0, 4) = "" 6368 * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..." 6369 * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..." 6370 * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..." 6371 * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..." 6372 * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..." 6373 * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..." 6374 * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno" 6375 * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno" 6376 * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno" 6377 * StringUtils.abbreviate("abcdefghij", 0, 3) = IllegalArgumentException 6378 * StringUtils.abbreviate("abcdefghij", 5, 6) = IllegalArgumentException 6379 * </pre> 6380 * 6381 * @param str the String to check, may be null 6382 * @param offset left edge of source String 6383 * @param maxWidth maximum length of result String, must be at least 4 6384 * @return abbreviated String, {@code null} if null String input 6385 * @throws IllegalArgumentException if the width is too small 6386 * @since 2.0 6387 */ 6388 public static String abbreviate(final String str, int offset, final int maxWidth) { 6389 if (str == null) { 6390 return null; 6391 } 6392 if (maxWidth < 4) { 6393 throw new IllegalArgumentException("Minimum abbreviation width is 4"); 6394 } 6395 if (str.length() <= maxWidth) { 6396 return str; 6397 } 6398 if (offset > str.length()) { 6399 offset = str.length(); 6400 } 6401 if (str.length() - offset < maxWidth - 3) { 6402 offset = str.length() - (maxWidth - 3); 6403 } 6404 final String abrevMarker = "..."; 6405 if (offset <= 4) { 6406 return str.substring(0, maxWidth - 3) + abrevMarker; 6407 } 6408 if (maxWidth < 7) { 6409 throw new IllegalArgumentException("Minimum abbreviation width with offset is 7"); 6410 } 6411 if (offset + maxWidth - 3 < str.length()) { 6412 return abrevMarker + abbreviate(str.substring(offset), maxWidth - 3); 6413 } 6414 return abrevMarker + str.substring(str.length() - (maxWidth - 3)); 6415 } 6416 6417 /** 6418 * <p>Abbreviates a String to the length passed, replacing the middle characters with the supplied 6419 * replacement String.</p> 6420 * 6421 * <p>This abbreviation only occurs if the following criteria is met: 6422 * <ul> 6423 * <li>Neither the String for abbreviation nor the replacement String are null or empty </li> 6424 * <li>The length to truncate to is less than the length of the supplied String</li> 6425 * <li>The length to truncate to is greater than 0</li> 6426 * <li>The abbreviated String will have enough room for the length supplied replacement String 6427 * and the first and last characters of the supplied String for abbreviation</li> 6428 * </ul> 6429 * Otherwise, the returned String will be the same as the supplied String for abbreviation. 6430 * </p> 6431 * 6432 * <pre> 6433 * StringUtils.abbreviateMiddle(null, null, 0) = null 6434 * StringUtils.abbreviateMiddle("abc", null, 0) = "abc" 6435 * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc" 6436 * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc" 6437 * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f" 6438 * </pre> 6439 * 6440 * @param str the String to abbreviate, may be null 6441 * @param middle the String to replace the middle characters with, may be null 6442 * @param length the length to abbreviate {@code str} to. 6443 * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation. 6444 * @since 2.5 6445 */ 6446 public static String abbreviateMiddle(final String str, final String middle, final int length) { 6447 if (isEmpty(str) || isEmpty(middle)) { 6448 return str; 6449 } 6450 6451 if (length >= str.length() || length < middle.length()+2) { 6452 return str; 6453 } 6454 6455 final int targetSting = length-middle.length(); 6456 final int startOffset = targetSting/2+targetSting%2; 6457 final int endOffset = str.length()-targetSting/2; 6458 6459 final StringBuilder builder = new StringBuilder(length); 6460 builder.append(str.substring(0,startOffset)); 6461 builder.append(middle); 6462 builder.append(str.substring(endOffset)); 6463 6464 return builder.toString(); 6465 } 6466 6467 // Difference 6468 //----------------------------------------------------------------------- 6469 /** 6470 * <p>Compares two Strings, and returns the portion where they differ. 6471 * More precisely, return the remainder of the second String, 6472 * starting from where it's different from the first. This means that 6473 * the difference between "abc" and "ab" is the empty String and not "c". </p> 6474 * 6475 * <p>For example, 6476 * {@code difference("i am a machine", "i am a robot") -> "robot"}.</p> 6477 * 6478 * <pre> 6479 * StringUtils.difference(null, null) = null 6480 * StringUtils.difference("", "") = "" 6481 * StringUtils.difference("", "abc") = "abc" 6482 * StringUtils.difference("abc", "") = "" 6483 * StringUtils.difference("abc", "abc") = "" 6484 * StringUtils.difference("abc", "ab") = "" 6485 * StringUtils.difference("ab", "abxyz") = "xyz" 6486 * StringUtils.difference("abcde", "abxyz") = "xyz" 6487 * StringUtils.difference("abcde", "xyz") = "xyz" 6488 * </pre> 6489 * 6490 * @param str1 the first String, may be null 6491 * @param str2 the second String, may be null 6492 * @return the portion of str2 where it differs from str1; returns the 6493 * empty String if they are equal 6494 * @see #indexOfDifference(CharSequence,CharSequence) 6495 * @since 2.0 6496 */ 6497 public static String difference(final String str1, final String str2) { 6498 if (str1 == null) { 6499 return str2; 6500 } 6501 if (str2 == null) { 6502 return str1; 6503 } 6504 final int at = indexOfDifference(str1, str2); 6505 if (at == INDEX_NOT_FOUND) { 6506 return EMPTY; 6507 } 6508 return str2.substring(at); 6509 } 6510 6511 /** 6512 * <p>Compares two CharSequences, and returns the index at which the 6513 * CharSequences begin to differ.</p> 6514 * 6515 * <p>For example, 6516 * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}</p> 6517 * 6518 * <pre> 6519 * StringUtils.indexOfDifference(null, null) = -1 6520 * StringUtils.indexOfDifference("", "") = -1 6521 * StringUtils.indexOfDifference("", "abc") = 0 6522 * StringUtils.indexOfDifference("abc", "") = 0 6523 * StringUtils.indexOfDifference("abc", "abc") = -1 6524 * StringUtils.indexOfDifference("ab", "abxyz") = 2 6525 * StringUtils.indexOfDifference("abcde", "abxyz") = 2 6526 * StringUtils.indexOfDifference("abcde", "xyz") = 0 6527 * </pre> 6528 * 6529 * @param cs1 the first CharSequence, may be null 6530 * @param cs2 the second CharSequence, may be null 6531 * @return the index where cs1 and cs2 begin to differ; -1 if they are equal 6532 * @since 2.0 6533 * @since 3.0 Changed signature from indexOfDifference(String, String) to 6534 * indexOfDifference(CharSequence, CharSequence) 6535 */ 6536 public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) { 6537 if (cs1 == cs2) { 6538 return INDEX_NOT_FOUND; 6539 } 6540 if (cs1 == null || cs2 == null) { 6541 return 0; 6542 } 6543 int i; 6544 for (i = 0; i < cs1.length() && i < cs2.length(); ++i) { 6545 if (cs1.charAt(i) != cs2.charAt(i)) { 6546 break; 6547 } 6548 } 6549 if (i < cs2.length() || i < cs1.length()) { 6550 return i; 6551 } 6552 return INDEX_NOT_FOUND; 6553 } 6554 6555 /** 6556 * <p>Compares all CharSequences in an array and returns the index at which the 6557 * CharSequences begin to differ.</p> 6558 * 6559 * <p>For example, 6560 * <code>indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7</code></p> 6561 * 6562 * <pre> 6563 * StringUtils.indexOfDifference(null) = -1 6564 * StringUtils.indexOfDifference(new String[] {}) = -1 6565 * StringUtils.indexOfDifference(new String[] {"abc"}) = -1 6566 * StringUtils.indexOfDifference(new String[] {null, null}) = -1 6567 * StringUtils.indexOfDifference(new String[] {"", ""}) = -1 6568 * StringUtils.indexOfDifference(new String[] {"", null}) = 0 6569 * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0 6570 * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0 6571 * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0 6572 * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0 6573 * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1 6574 * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1 6575 * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2 6576 * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2 6577 * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0 6578 * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0 6579 * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7 6580 * </pre> 6581 * 6582 * @param css array of CharSequences, entries may be null 6583 * @return the index where the strings begin to differ; -1 if they are all equal 6584 * @since 2.4 6585 * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...) 6586 */ 6587 public static int indexOfDifference(final CharSequence... css) { 6588 if (css == null || css.length <= 1) { 6589 return INDEX_NOT_FOUND; 6590 } 6591 boolean anyStringNull = false; 6592 boolean allStringsNull = true; 6593 final int arrayLen = css.length; 6594 int shortestStrLen = Integer.MAX_VALUE; 6595 int longestStrLen = 0; 6596 6597 // find the min and max string lengths; this avoids checking to make 6598 // sure we are not exceeding the length of the string each time through 6599 // the bottom loop. 6600 for (int i = 0; i < arrayLen; i++) { 6601 if (css[i] == null) { 6602 anyStringNull = true; 6603 shortestStrLen = 0; 6604 } else { 6605 allStringsNull = false; 6606 shortestStrLen = Math.min(css[i].length(), shortestStrLen); 6607 longestStrLen = Math.max(css[i].length(), longestStrLen); 6608 } 6609 } 6610 6611 // handle lists containing all nulls or all empty strings 6612 if (allStringsNull || longestStrLen == 0 && !anyStringNull) { 6613 return INDEX_NOT_FOUND; 6614 } 6615 6616 // handle lists containing some nulls or some empty strings 6617 if (shortestStrLen == 0) { 6618 return 0; 6619 } 6620 6621 // find the position with the first difference across all strings 6622 int firstDiff = -1; 6623 for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) { 6624 final char comparisonChar = css[0].charAt(stringPos); 6625 for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) { 6626 if (css[arrayPos].charAt(stringPos) != comparisonChar) { 6627 firstDiff = stringPos; 6628 break; 6629 } 6630 } 6631 if (firstDiff != -1) { 6632 break; 6633 } 6634 } 6635 6636 if (firstDiff == -1 && shortestStrLen != longestStrLen) { 6637 // we compared all of the characters up to the length of the 6638 // shortest string and didn't find a match, but the string lengths 6639 // vary, so return the length of the shortest string. 6640 return shortestStrLen; 6641 } 6642 return firstDiff; 6643 } 6644 6645 /** 6646 * <p>Compares all Strings in an array and returns the initial sequence of 6647 * characters that is common to all of them.</p> 6648 * 6649 * <p>For example, 6650 * <code>getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "</code></p> 6651 * 6652 * <pre> 6653 * StringUtils.getCommonPrefix(null) = "" 6654 * StringUtils.getCommonPrefix(new String[] {}) = "" 6655 * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc" 6656 * StringUtils.getCommonPrefix(new String[] {null, null}) = "" 6657 * StringUtils.getCommonPrefix(new String[] {"", ""}) = "" 6658 * StringUtils.getCommonPrefix(new String[] {"", null}) = "" 6659 * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = "" 6660 * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = "" 6661 * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = "" 6662 * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = "" 6663 * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc" 6664 * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a" 6665 * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab" 6666 * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab" 6667 * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = "" 6668 * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = "" 6669 * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a " 6670 * </pre> 6671 * 6672 * @param strs array of String objects, entries may be null 6673 * @return the initial sequence of characters that are common to all Strings 6674 * in the array; empty String if the array is null, the elements are all null 6675 * or if there is no common prefix. 6676 * @since 2.4 6677 */ 6678 public static String getCommonPrefix(final String... strs) { 6679 if (strs == null || strs.length == 0) { 6680 return EMPTY; 6681 } 6682 final int smallestIndexOfDiff = indexOfDifference(strs); 6683 if (smallestIndexOfDiff == INDEX_NOT_FOUND) { 6684 // all strings were identical 6685 if (strs[0] == null) { 6686 return EMPTY; 6687 } 6688 return strs[0]; 6689 } else if (smallestIndexOfDiff == 0) { 6690 // there were no common initial characters 6691 return EMPTY; 6692 } else { 6693 // we found a common initial character sequence 6694 return strs[0].substring(0, smallestIndexOfDiff); 6695 } 6696 } 6697 6698 // Misc 6699 //----------------------------------------------------------------------- 6700 /** 6701 * <p>Find the Levenshtein distance between two Strings.</p> 6702 * 6703 * <p>This is the number of changes needed to change one String into 6704 * another, where each change is a single character modification (deletion, 6705 * insertion or substitution).</p> 6706 * 6707 * <p>The previous implementation of the Levenshtein distance algorithm 6708 * was from <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p> 6709 * 6710 * <p>Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError 6711 * which can occur when my Java implementation is used with very large strings.<br> 6712 * This implementation of the Levenshtein distance algorithm 6713 * is from <a href="http://www.merriampark.com/ldjava.htm">http://www.merriampark.com/ldjava.htm</a></p> 6714 * 6715 * <pre> 6716 * StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException 6717 * StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException 6718 * StringUtils.getLevenshteinDistance("","") = 0 6719 * StringUtils.getLevenshteinDistance("","a") = 1 6720 * StringUtils.getLevenshteinDistance("aaapppp", "") = 7 6721 * StringUtils.getLevenshteinDistance("frog", "fog") = 1 6722 * StringUtils.getLevenshteinDistance("fly", "ant") = 3 6723 * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7 6724 * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7 6725 * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8 6726 * StringUtils.getLevenshteinDistance("hello", "hallo") = 1 6727 * </pre> 6728 * 6729 * @param s the first String, must not be null 6730 * @param t the second String, must not be null 6731 * @return result distance 6732 * @throws IllegalArgumentException if either String input {@code null} 6733 * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to 6734 * getLevenshteinDistance(CharSequence, CharSequence) 6735 */ 6736 public static int getLevenshteinDistance(CharSequence s, CharSequence t) { 6737 if (s == null || t == null) { 6738 throw new IllegalArgumentException("Strings must not be null"); 6739 } 6740 6741 /* 6742 The difference between this impl. and the previous is that, rather 6743 than creating and retaining a matrix of size s.length() + 1 by t.length() + 1, 6744 we maintain two single-dimensional arrays of length s.length() + 1. The first, d, 6745 is the 'current working' distance array that maintains the newest distance cost 6746 counts as we iterate through the characters of String s. Each time we increment 6747 the index of String t we are comparing, d is copied to p, the second int[]. Doing so 6748 allows us to retain the previous cost counts as required by the algorithm (taking 6749 the minimum of the cost count to the left, up one, and diagonally up and to the left 6750 of the current cost count being calculated). (Note that the arrays aren't really 6751 copied anymore, just switched...this is clearly much better than cloning an array 6752 or doing a System.arraycopy() each time through the outer loop.) 6753 6754 Effectively, the difference between the two implementations is this one does not 6755 cause an out of memory condition when calculating the LD over two very large strings. 6756 */ 6757 6758 int n = s.length(); // length of s 6759 int m = t.length(); // length of t 6760 6761 if (n == 0) { 6762 return m; 6763 } else if (m == 0) { 6764 return n; 6765 } 6766 6767 if (n > m) { 6768 // swap the input strings to consume less memory 6769 final CharSequence tmp = s; 6770 s = t; 6771 t = tmp; 6772 n = m; 6773 m = t.length(); 6774 } 6775 6776 int p[] = new int[n + 1]; //'previous' cost array, horizontally 6777 int d[] = new int[n + 1]; // cost array, horizontally 6778 int _d[]; //placeholder to assist in swapping p and d 6779 6780 // indexes into strings s and t 6781 int i; // iterates through s 6782 int j; // iterates through t 6783 6784 char t_j; // jth character of t 6785 6786 int cost; // cost 6787 6788 for (i = 0; i <= n; i++) { 6789 p[i] = i; 6790 } 6791 6792 for (j = 1; j <= m; j++) { 6793 t_j = t.charAt(j - 1); 6794 d[0] = j; 6795 6796 for (i = 1; i <= n; i++) { 6797 cost = s.charAt(i - 1) == t_j ? 0 : 1; 6798 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost 6799 d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost); 6800 } 6801 6802 // copy current distance counts to 'previous row' distance counts 6803 _d = p; 6804 p = d; 6805 d = _d; 6806 } 6807 6808 // our last action in the above loop was to switch d and p, so p now 6809 // actually has the most recent cost counts 6810 return p[n]; 6811 } 6812 6813 /** 6814 * <p>Find the Levenshtein distance between two Strings if it's less than or equal to a given 6815 * threshold.</p> 6816 * 6817 * <p>This is the number of changes needed to change one String into 6818 * another, where each change is a single character modification (deletion, 6819 * insertion or substitution).</p> 6820 * 6821 * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield 6822 * and Chas Emerick's implementation of the Levenshtein distance algorithm from 6823 * <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p> 6824 * 6825 * <pre> 6826 * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException 6827 * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException 6828 * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException 6829 * StringUtils.getLevenshteinDistance("","", 0) = 0 6830 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 6831 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 6832 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 6833 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 6834 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 6835 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 6836 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 6837 * </pre> 6838 * 6839 * @param s the first String, must not be null 6840 * @param t the second String, must not be null 6841 * @param threshold the target threshold, must not be negative 6842 * @return result distance, or {@code -1} if the distance would be greater than the threshold 6843 * @throws IllegalArgumentException if either String input {@code null} or negative threshold 6844 */ 6845 public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) { 6846 if (s == null || t == null) { 6847 throw new IllegalArgumentException("Strings must not be null"); 6848 } 6849 if (threshold < 0) { 6850 throw new IllegalArgumentException("Threshold must not be negative"); 6851 } 6852 6853 /* 6854 This implementation only computes the distance if it's less than or equal to the 6855 threshold value, returning -1 if it's greater. The advantage is performance: unbounded 6856 distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only 6857 computing a diagonal stripe of width 2k + 1 of the cost table. 6858 It is also possible to use this to compute the unbounded Levenshtein distance by starting 6859 the threshold at 1 and doubling each time until the distance is found; this is O(dm), where 6860 d is the distance. 6861 6862 One subtlety comes from needing to ignore entries on the border of our stripe 6863 eg. 6864 p[] = |#|#|#|* 6865 d[] = *|#|#|#| 6866 We must ignore the entry to the left of the leftmost member 6867 We must ignore the entry above the rightmost member 6868 6869 Another subtlety comes from our stripe running off the matrix if the strings aren't 6870 of the same size. Since string s is always swapped to be the shorter of the two, 6871 the stripe will always run off to the upper right instead of the lower left of the matrix. 6872 6873 As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. 6874 In this case we're going to walk a stripe of length 3. The matrix would look like so: 6875 6876 1 2 3 4 5 6877 1 |#|#| | | | 6878 2 |#|#|#| | | 6879 3 | |#|#|#| | 6880 4 | | |#|#|#| 6881 5 | | | |#|#| 6882 6 | | | | |#| 6883 7 | | | | | | 6884 6885 Note how the stripe leads off the table as there is no possible way to turn a string of length 5 6886 into one of length 7 in edit distance of 1. 6887 6888 Additionally, this implementation decreases memory usage by using two 6889 single-dimensional arrays and swapping them back and forth instead of allocating 6890 an entire n by m matrix. This requires a few minor changes, such as immediately returning 6891 when it's detected that the stripe has run off the matrix and initially filling the arrays with 6892 large values so that entries we don't compute are ignored. 6893 6894 See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. 6895 */ 6896 6897 int n = s.length(); // length of s 6898 int m = t.length(); // length of t 6899 6900 // if one string is empty, the edit distance is necessarily the length of the other 6901 if (n == 0) { 6902 return m <= threshold ? m : -1; 6903 } else if (m == 0) { 6904 return n <= threshold ? n : -1; 6905 } 6906 6907 if (n > m) { 6908 // swap the two strings to consume less memory 6909 final CharSequence tmp = s; 6910 s = t; 6911 t = tmp; 6912 n = m; 6913 m = t.length(); 6914 } 6915 6916 int p[] = new int[n + 1]; // 'previous' cost array, horizontally 6917 int d[] = new int[n + 1]; // cost array, horizontally 6918 int _d[]; // placeholder to assist in swapping p and d 6919 6920 // fill in starting table values 6921 final int boundary = Math.min(n, threshold) + 1; 6922 for (int i = 0; i < boundary; i++) { 6923 p[i] = i; 6924 } 6925 // these fills ensure that the value above the rightmost entry of our 6926 // stripe will be ignored in following loop iterations 6927 Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); 6928 Arrays.fill(d, Integer.MAX_VALUE); 6929 6930 // iterates through t 6931 for (int j = 1; j <= m; j++) { 6932 final char t_j = t.charAt(j - 1); // jth character of t 6933 d[0] = j; 6934 6935 // compute stripe indices, constrain to array size 6936 final int min = Math.max(1, j - threshold); 6937 final int max = Math.min(n, j + threshold); 6938 6939 // the stripe may lead off of the table if s and t are of different sizes 6940 if (min > max) { 6941 return -1; 6942 } 6943 6944 // ignore entry left of leftmost 6945 if (min > 1) { 6946 d[min - 1] = Integer.MAX_VALUE; 6947 } 6948 6949 // iterates through [min, max] in s 6950 for (int i = min; i <= max; i++) { 6951 if (s.charAt(i - 1) == t_j) { 6952 // diagonally left and up 6953 d[i] = p[i - 1]; 6954 } else { 6955 // 1 + minimum of cell to the left, to the top, diagonally left and up 6956 d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); 6957 } 6958 } 6959 6960 // copy current distance counts to 'previous row' distance counts 6961 _d = p; 6962 p = d; 6963 d = _d; 6964 } 6965 6966 // if p[n] is greater than the threshold, there's no guarantee on it being the correct 6967 // distance 6968 if (p[n] <= threshold) { 6969 return p[n]; 6970 } 6971 return -1; 6972 } 6973 6974 // startsWith 6975 //----------------------------------------------------------------------- 6976 6977 /** 6978 * <p>Check if a CharSequence starts with a specified prefix.</p> 6979 * 6980 * <p>{@code null}s are handled without exceptions. Two {@code null} 6981 * references are considered to be equal. The comparison is case sensitive.</p> 6982 * 6983 * <pre> 6984 * StringUtils.startsWith(null, null) = true 6985 * StringUtils.startsWith(null, "abc") = false 6986 * StringUtils.startsWith("abcdef", null) = false 6987 * StringUtils.startsWith("abcdef", "abc") = true 6988 * StringUtils.startsWith("ABCDEF", "abc") = false 6989 * </pre> 6990 * 6991 * @see java.lang.String#startsWith(String) 6992 * @param str the CharSequence to check, may be null 6993 * @param prefix the prefix to find, may be null 6994 * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or 6995 * both {@code null} 6996 * @since 2.4 6997 * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence) 6998 */ 6999 public static boolean startsWith(final CharSequence str, final CharSequence prefix) { 7000 return startsWith(str, prefix, false); 7001 } 7002 7003 /** 7004 * <p>Case insensitive check if a CharSequence starts with a specified prefix.</p> 7005 * 7006 * <p>{@code null}s are handled without exceptions. Two {@code null} 7007 * references are considered to be equal. The comparison is case insensitive.</p> 7008 * 7009 * <pre> 7010 * StringUtils.startsWithIgnoreCase(null, null) = true 7011 * StringUtils.startsWithIgnoreCase(null, "abc") = false 7012 * StringUtils.startsWithIgnoreCase("abcdef", null) = false 7013 * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true 7014 * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true 7015 * </pre> 7016 * 7017 * @see java.lang.String#startsWith(String) 7018 * @param str the CharSequence to check, may be null 7019 * @param prefix the prefix to find, may be null 7020 * @return {@code true} if the CharSequence starts with the prefix, case insensitive, or 7021 * both {@code null} 7022 * @since 2.4 7023 * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence) 7024 */ 7025 public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) { 7026 return startsWith(str, prefix, true); 7027 } 7028 7029 /** 7030 * <p>Check if a CharSequence starts with a specified prefix (optionally case insensitive).</p> 7031 * 7032 * @see java.lang.String#startsWith(String) 7033 * @param str the CharSequence to check, may be null 7034 * @param prefix the prefix to find, may be null 7035 * @param ignoreCase indicates whether the compare should ignore case 7036 * (case insensitive) or not. 7037 * @return {@code true} if the CharSequence starts with the prefix or 7038 * both {@code null} 7039 */ 7040 private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) { 7041 if (str == null || prefix == null) { 7042 return str == null && prefix == null; 7043 } 7044 if (prefix.length() > str.length()) { 7045 return false; 7046 } 7047 return CharSequenceUtils.regionMatches(str, ignoreCase, 0, prefix, 0, prefix.length()); 7048 } 7049 7050 /** 7051 * <p>Check if a CharSequence starts with any of an array of specified strings.</p> 7052 * 7053 * <pre> 7054 * StringUtils.startsWithAny(null, null) = false 7055 * StringUtils.startsWithAny(null, new String[] {"abc"}) = false 7056 * StringUtils.startsWithAny("abcxyz", null) = false 7057 * StringUtils.startsWithAny("abcxyz", new String[] {""}) = false 7058 * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true 7059 * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 7060 * </pre> 7061 * 7062 * @param string the CharSequence to check, may be null 7063 * @param searchStrings the CharSequences to find, may be null or empty 7064 * @return {@code true} if the CharSequence starts with any of the the prefixes, case insensitive, or 7065 * both {@code null} 7066 * @since 2.5 7067 * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...) 7068 */ 7069 public static boolean startsWithAny(final CharSequence string, final CharSequence... searchStrings) { 7070 if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) { 7071 return false; 7072 } 7073 for (final CharSequence searchString : searchStrings) { 7074 if (StringUtils.startsWith(string, searchString)) { 7075 return true; 7076 } 7077 } 7078 return false; 7079 } 7080 7081 // endsWith 7082 //----------------------------------------------------------------------- 7083 7084 /** 7085 * <p>Check if a CharSequence ends with a specified suffix.</p> 7086 * 7087 * <p>{@code null}s are handled without exceptions. Two {@code null} 7088 * references are considered to be equal. The comparison is case sensitive.</p> 7089 * 7090 * <pre> 7091 * StringUtils.endsWith(null, null) = true 7092 * StringUtils.endsWith(null, "def") = false 7093 * StringUtils.endsWith("abcdef", null) = false 7094 * StringUtils.endsWith("abcdef", "def") = true 7095 * StringUtils.endsWith("ABCDEF", "def") = false 7096 * StringUtils.endsWith("ABCDEF", "cde") = false 7097 * </pre> 7098 * 7099 * @see java.lang.String#endsWith(String) 7100 * @param str the CharSequence to check, may be null 7101 * @param suffix the suffix to find, may be null 7102 * @return {@code true} if the CharSequence ends with the suffix, case sensitive, or 7103 * both {@code null} 7104 * @since 2.4 7105 * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence) 7106 */ 7107 public static boolean endsWith(final CharSequence str, final CharSequence suffix) { 7108 return endsWith(str, suffix, false); 7109 } 7110 7111 /** 7112 * <p>Case insensitive check if a CharSequence ends with a specified suffix.</p> 7113 * 7114 * <p>{@code null}s are handled without exceptions. Two {@code null} 7115 * references are considered to be equal. The comparison is case insensitive.</p> 7116 * 7117 * <pre> 7118 * StringUtils.endsWithIgnoreCase(null, null) = true 7119 * StringUtils.endsWithIgnoreCase(null, "def") = false 7120 * StringUtils.endsWithIgnoreCase("abcdef", null) = false 7121 * StringUtils.endsWithIgnoreCase("abcdef", "def") = true 7122 * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true 7123 * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false 7124 * </pre> 7125 * 7126 * @see java.lang.String#endsWith(String) 7127 * @param str the CharSequence to check, may be null 7128 * @param suffix the suffix to find, may be null 7129 * @return {@code true} if the CharSequence ends with the suffix, case insensitive, or 7130 * both {@code null} 7131 * @since 2.4 7132 * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence) 7133 */ 7134 public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) { 7135 return endsWith(str, suffix, true); 7136 } 7137 7138 /** 7139 * <p>Check if a CharSequence ends with a specified suffix (optionally case insensitive).</p> 7140 * 7141 * @see java.lang.String#endsWith(String) 7142 * @param str the CharSequence to check, may be null 7143 * @param suffix the suffix to find, may be null 7144 * @param ignoreCase indicates whether the compare should ignore case 7145 * (case insensitive) or not. 7146 * @return {@code true} if the CharSequence starts with the prefix or 7147 * both {@code null} 7148 */ 7149 private static boolean endsWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) { 7150 if (str == null || suffix == null) { 7151 return str == null && suffix == null; 7152 } 7153 if (suffix.length() > str.length()) { 7154 return false; 7155 } 7156 final int strOffset = str.length() - suffix.length(); 7157 return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset, suffix, 0, suffix.length()); 7158 } 7159 7160 /** 7161 * <p> 7162 * Similar to <a 7163 * href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize 7164 * -space</a> 7165 * </p> 7166 * <p> 7167 * The function returns the argument string with whitespace normalized by using 7168 * <code>{@link #trim(String)}</code> to remove leading and trailing whitespace 7169 * and then replacing sequences of whitespace characters by a single space. 7170 * </p> 7171 * In XML Whitespace characters are the same as those allowed by the <a 7172 * href="http://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | #x9 | #xD | #xA)+ 7173 * <p> 7174 * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r] 7175 * <p> 7176 * For reference: 7177 * <ul> 7178 * <li>\x0B = vertical tab</li> 7179 * <li>\f = #xC = form feed</li> 7180 * <li>#x20 = space</li> 7181 * <li>#x9 = \t</li> 7182 * <li>#xA = \n</li> 7183 * <li>#xD = \r</li> 7184 * </ul> 7185 * </p> 7186 * <p> 7187 * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also 7188 * normalize. Additionally <code>{@link #trim(String)}</code> removes control characters (char <= 32) from both 7189 * ends of this String. 7190 * </p> 7191 * 7192 * @see Pattern 7193 * @see #trim(String) 7194 * @see <a 7195 * href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize-space</a> 7196 * @param str the source String to normalize whitespaces from, may be null 7197 * @return the modified string with whitespace normalized, {@code null} if null String input 7198 * 7199 * @since 3.0 7200 */ 7201 public static String normalizeSpace(final String str) { 7202 if (str == null) { 7203 return null; 7204 } 7205 return WHITESPACE_PATTERN.matcher(trim(str)).replaceAll(SPACE); 7206 } 7207 7208 /** 7209 * <p>Check if a CharSequence ends with any of an array of specified strings.</p> 7210 * 7211 * <pre> 7212 * StringUtils.endsWithAny(null, null) = false 7213 * StringUtils.endsWithAny(null, new String[] {"abc"}) = false 7214 * StringUtils.endsWithAny("abcxyz", null) = false 7215 * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true 7216 * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true 7217 * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true 7218 * </pre> 7219 * 7220 * @param string the CharSequence to check, may be null 7221 * @param searchStrings the CharSequences to find, may be null or empty 7222 * @return {@code true} if the CharSequence ends with any of the the prefixes, case insensitive, or 7223 * both {@code null} 7224 * @since 3.0 7225 */ 7226 public static boolean endsWithAny(final CharSequence string, final CharSequence... searchStrings) { 7227 if (isEmpty(string) || ArrayUtils.isEmpty(searchStrings)) { 7228 return false; 7229 } 7230 for (final CharSequence searchString : searchStrings) { 7231 if (StringUtils.endsWith(string, searchString)) { 7232 return true; 7233 } 7234 } 7235 return false; 7236 } 7237 7238 /** 7239 * Appends the suffix to the end of the string if the string does not 7240 * already end in the suffix. 7241 * 7242 * @param str The string. 7243 * @param suffix The suffix to append to the end of the string. 7244 * @param ignoreCase Indicates whether the compare should ignore case. 7245 * @param suffixes Additional suffixes that are valid terminators (optional). 7246 * 7247 * @return A new String if suffix was appened, the same string otherwise. 7248 */ 7249 private static String appendIfMissing(final String str, final CharSequence suffix, final boolean ignoreCase, final CharSequence... suffixes) { 7250 if (str == null || isEmpty(suffix) || endsWith(str, suffix, ignoreCase)) { 7251 return str; 7252 } 7253 if (suffixes != null && suffixes.length > 0) { 7254 for (final CharSequence s : suffixes) { 7255 if (endsWith(str, s, ignoreCase)) { 7256 return str; 7257 } 7258 } 7259 } 7260 return str + suffix.toString(); 7261 } 7262 7263 /** 7264 * Appends the suffix to the end of the string if the string does not 7265 * already end with any the suffixes. 7266 * 7267 * <pre> 7268 * StringUtils.appendIfMissing(null, null) = null 7269 * StringUtils.appendIfMissing("abc", null) = "abc" 7270 * StringUtils.appendIfMissing("", "xyz") = "xyz" 7271 * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz" 7272 * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz" 7273 * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz" 7274 * </pre> 7275 * <p>With additional suffixes,</p> 7276 * <pre> 7277 * StringUtils.appendIfMissing(null, null, null) = null 7278 * StringUtils.appendIfMissing("abc", null, null) = "abc" 7279 * StringUtils.appendIfMissing("", "xyz", null) = "xyz" 7280 * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 7281 * StringUtils.appendIfMissing("abc", "xyz", "") = "abc" 7282 * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz" 7283 * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz" 7284 * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno" 7285 * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz" 7286 * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz" 7287 * </pre> 7288 * 7289 * @param str The string. 7290 * @param suffix The suffix to append to the end of the string. 7291 * @param suffixes Additional suffixes that are valid terminators. 7292 * 7293 * @return A new String if suffix was appened, the same string otherwise. 7294 * 7295 * @since 3.2 7296 */ 7297 public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) { 7298 return appendIfMissing(str, suffix, false, suffixes); 7299 } 7300 7301 /** 7302 * Appends the suffix to the end of the string if the string does not 7303 * already end, case insensitive, with any of the suffixes. 7304 * 7305 * <pre> 7306 * StringUtils.appendIfMissingIgnoreCase(null, null) = null 7307 * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc" 7308 * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz" 7309 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz" 7310 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz" 7311 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ" 7312 * </pre> 7313 * <p>With additional suffixes,</p> 7314 * <pre> 7315 * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null 7316 * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc" 7317 * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz" 7318 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz" 7319 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc" 7320 * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "axyz" 7321 * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz" 7322 * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno" 7323 * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ" 7324 * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO" 7325 * </pre> 7326 * 7327 * @param str The string. 7328 * @param suffix The suffix to append to the end of the string. 7329 * @param suffixes Additional suffixes that are valid terminators. 7330 * 7331 * @return A new String if suffix was appened, the same string otherwise. 7332 * 7333 * @since 3.2 7334 */ 7335 public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) { 7336 return appendIfMissing(str, suffix, true, suffixes); 7337 } 7338 7339 /** 7340 * Prepends the prefix to the start of the string if the string does not 7341 * already start with any of the prefixes. 7342 * 7343 * @param str The string. 7344 * @param prefix The prefix to prepend to the start of the string. 7345 * @param ignoreCase Indicates whether the compare should ignore case. 7346 * @param prefixes Additional prefixes that are valid (optional). 7347 * 7348 * @return A new String if prefix was prepended, the same string otherwise. 7349 */ 7350 private static String prependIfMissing(final String str, final CharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes) { 7351 if (str == null || isEmpty(prefix) || startsWith(str, prefix, ignoreCase)) { 7352 return str; 7353 } 7354 if (prefixes != null && prefixes.length > 0) { 7355 for (final CharSequence p : prefixes) { 7356 if (startsWith(str, p, ignoreCase)) { 7357 return str; 7358 } 7359 } 7360 } 7361 return prefix.toString() + str; 7362 } 7363 7364 /** 7365 * Prepends the prefix to the start of the string if the string does not 7366 * already start with any of the prefixes. 7367 * 7368 * <pre> 7369 * StringUtils.prependIfMissing(null, null) = null 7370 * StringUtils.prependIfMissing("abc", null) = "abc" 7371 * StringUtils.prependIfMissing("", "xyz") = "xyz" 7372 * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc" 7373 * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc" 7374 * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc" 7375 * </pre> 7376 * <p>With additional prefixes,</p> 7377 * <pre> 7378 * StringUtils.prependIfMissing(null, null, null) = null 7379 * StringUtils.prependIfMissing("abc", null, null) = "abc" 7380 * StringUtils.prependIfMissing("", "xyz", null) = "xyz" 7381 * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 7382 * StringUtils.prependIfMissing("abc", "xyz", "") = "abc" 7383 * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc" 7384 * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc" 7385 * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc" 7386 * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc" 7387 * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc" 7388 * </pre> 7389 * 7390 * @param str The string. 7391 * @param prefix The prefix to prepend to the start of the string. 7392 * @param prefixes Additional prefixes that are valid. 7393 * 7394 * @return A new String if prefix was prepended, the same string otherwise. 7395 * 7396 * @since 3.2 7397 */ 7398 public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) { 7399 return prependIfMissing(str, prefix, false, prefixes); 7400 } 7401 7402 /** 7403 * Prepends the prefix to the start of the string if the string does not 7404 * already start, case insensitive, with any of the prefixes. 7405 * 7406 * <pre> 7407 * StringUtils.prependIfMissingIgnoreCase(null, null) = null 7408 * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc" 7409 * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz" 7410 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc" 7411 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc" 7412 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc" 7413 * </pre> 7414 * <p>With additional prefixes,</p> 7415 * <pre> 7416 * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null 7417 * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc" 7418 * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz" 7419 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc" 7420 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc" 7421 * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc" 7422 * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc" 7423 * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc" 7424 * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc" 7425 * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc" 7426 * </pre> 7427 * 7428 * @param str The string. 7429 * @param prefix The prefix to prepend to the start of the string. 7430 * @param prefixes Additional prefixes that are valid (optional). 7431 * 7432 * @return A new String if prefix was prepended, the same string otherwise. 7433 * 7434 * @since 3.2 7435 */ 7436 public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) { 7437 return prependIfMissing(str, prefix, true, prefixes); 7438 } 7439 7440 /** 7441 * Converts a <code>byte[]</code> to a String using the specified character encoding. 7442 * 7443 * @param bytes 7444 * the byte array to read from 7445 * @param charsetName 7446 * the encoding to use, if null then use the platform default 7447 * @return a new String 7448 * @throws UnsupportedEncodingException 7449 * If the named charset is not supported 7450 * @throws NullPointerException 7451 * if the input is null 7452 * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)} instead to String constants in your code 7453 * @since 3.1 7454 */ 7455 public static String toString(final byte[] bytes, final String charsetName) throws UnsupportedEncodingException { 7456 return charsetName != null ? new String(bytes, charsetName) : new String(bytes, Charset.defaultCharset()); 7457 } 7458 7459 /** 7460 * Converts a <code>byte[]</code> to a String using the specified character encoding. 7461 * 7462 * @param bytes 7463 * the byte array to read from 7464 * @param charset 7465 * the encoding to use, if null then use the platform default 7466 * @return a new String 7467 * @throws UnsupportedEncodingException 7468 * If the named charset is not supported 7469 * @throws NullPointerException 7470 * if the input is null 7471 * @since 3.2 7472 */ 7473 public static String toEncodedString(byte[] bytes, Charset charset) throws UnsupportedEncodingException { 7474 return new String(bytes, charset != null ? charset : Charset.defaultCharset()); 7475 } 7476 7477}