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