source: src/main/java/agents/org/apache/commons/lang/StringUtils.java

Last change on this file was 127, checked in by Wouter Pasman, 6 years ago

#41 ROLL BACK of rev.126 . So this version is equal to rev. 125

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