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