• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
17 package org.apache.commons.lang3;
18 
19 import java.util.Objects;
20 
21 /**
22  * Operations on char primitives and Character objects.
23  *
24  * <p>This class tries to handle {@code null} input gracefully.
25  * An exception will not be thrown for a {@code null} input.
26  * Each method documents its behavior in more detail.</p>
27  *
28  * <p>#ThreadSafe#</p>
29  * @since 2.1
30  */
31 public class CharUtils {
32 
33     private static final String[] CHAR_STRING_ARRAY = new String[128];
34 
35     private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
36 
37     /**
38      * Linefeed character LF ({@code '\n'}, Unicode 000a).
39      *
40      * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
41      *      for Character and String Literals</a>
42      * @since 2.2
43      */
44     public static final char LF = '\n';
45 
46     /**
47      * Carriage return character CR ('\r', Unicode 000d).
48      *
49      * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
50      *      for Character and String Literals</a>
51      * @since 2.2
52      */
53     public static final char CR = '\r';
54 
55     /**
56      * {@code \u0000} null control character ('\0'), abbreviated NUL.
57      *
58      * @since 3.6
59      */
60     public static final char NUL = '\0';
61 
62     static {
ArrayUtils.setAll(CHAR_STRING_ARRAY, i -> String.valueOf((char) i))63         ArrayUtils.setAll(CHAR_STRING_ARRAY, i -> String.valueOf((char) i));
64     }
65 
66     /**
67      * {@link CharUtils} instances should NOT be constructed in standard programming.
68      * Instead, the class should be used as {@code CharUtils.toString('c');}.
69      *
70      * <p>This constructor is public to permit tools that require a JavaBean instance
71      * to operate.</p>
72      */
CharUtils()73     public CharUtils() {
74     }
75 
76     /**
77      * Converts the character to a Character.
78      *
79      * <p>For ASCII 7 bit characters, this uses a cache that will return the
80      * same Character object each time.</p>
81      *
82      * <pre>
83      *   CharUtils.toCharacterObject(' ')  = ' '
84      *   CharUtils.toCharacterObject('A')  = 'A'
85      * </pre>
86      *
87      * @deprecated Java 5 introduced {@link Character#valueOf(char)} which caches chars 0 through 127.
88      * @param ch  the character to convert
89      * @return a Character of the specified character
90      */
91     @Deprecated
toCharacterObject(final char ch)92     public static Character toCharacterObject(final char ch) {
93         return Character.valueOf(ch);
94     }
95 
96     /**
97      * Converts the String to a Character using the first character, returning
98      * null for empty Strings.
99      *
100      * <p>For ASCII 7 bit characters, this uses a cache that will return the
101      * same Character object each time.</p>
102      *
103      * <pre>
104      *   CharUtils.toCharacterObject(null) = null
105      *   CharUtils.toCharacterObject("")   = null
106      *   CharUtils.toCharacterObject("A")  = 'A'
107      *   CharUtils.toCharacterObject("BA") = 'B'
108      * </pre>
109      *
110      * @param str  the character to convert
111      * @return the Character value of the first letter of the String
112      */
toCharacterObject(final String str)113     public static Character toCharacterObject(final String str) {
114         return StringUtils.isEmpty(str) ? null : Character.valueOf(str.charAt(0));
115     }
116 
117     /**
118      * Converts the Character to a char throwing an exception for {@code null}.
119      *
120      * <pre>
121      *   CharUtils.toChar(' ')  = ' '
122      *   CharUtils.toChar('A')  = 'A'
123      *   CharUtils.toChar(null) throws IllegalArgumentException
124      * </pre>
125      *
126      * @param ch  the character to convert
127      * @return the char value of the Character
128      * @throws NullPointerException if the Character is null
129      */
toChar(final Character ch)130     public static char toChar(final Character ch) {
131         return Objects.requireNonNull(ch, "ch").charValue();
132     }
133 
134     /**
135      * Converts the Character to a char handling {@code null}.
136      *
137      * <pre>
138      *   CharUtils.toChar(null, 'X') = 'X'
139      *   CharUtils.toChar(' ', 'X')  = ' '
140      *   CharUtils.toChar('A', 'X')  = 'A'
141      * </pre>
142      *
143      * @param ch  the character to convert
144      * @param defaultValue  the value to use if the  Character is null
145      * @return the char value of the Character or the default if null
146      */
toChar(final Character ch, final char defaultValue)147     public static char toChar(final Character ch, final char defaultValue) {
148         return ch != null ? ch.charValue() : defaultValue;
149     }
150 
151     /**
152      * Converts the String to a char using the first character, throwing
153      * an exception on empty Strings.
154      *
155      * <pre>
156      *   CharUtils.toChar("A")  = 'A'
157      *   CharUtils.toChar("BA") = 'B'
158      *   CharUtils.toChar(null) throws IllegalArgumentException
159      *   CharUtils.toChar("")   throws IllegalArgumentException
160      * </pre>
161      *
162      * @param str  the character to convert
163      * @return the char value of the first letter of the String
164      * @throws NullPointerException if the string is null
165      * @throws IllegalArgumentException if the String is empty
166      */
toChar(final String str)167     public static char toChar(final String str) {
168         Validate.notEmpty(str, "The String must not be empty");
169         return str.charAt(0);
170     }
171 
172     /**
173      * Converts the String to a char using the first character, defaulting
174      * the value on empty Strings.
175      *
176      * <pre>
177      *   CharUtils.toChar(null, 'X') = 'X'
178      *   CharUtils.toChar("", 'X')   = 'X'
179      *   CharUtils.toChar("A", 'X')  = 'A'
180      *   CharUtils.toChar("BA", 'X') = 'B'
181      * </pre>
182      *
183      * @param str  the character to convert
184      * @param defaultValue  the value to use if the  Character is null
185      * @return the char value of the first letter of the String or the default if null
186      */
toChar(final String str, final char defaultValue)187     public static char toChar(final String str, final char defaultValue) {
188         return StringUtils.isEmpty(str) ? defaultValue : str.charAt(0);
189     }
190 
191     /**
192      * Converts the character to the Integer it represents, throwing an
193      * exception if the character is not numeric.
194      *
195      * <p>This method converts the char '1' to the int 1 and so on.</p>
196      *
197      * <pre>
198      *   CharUtils.toIntValue('3')  = 3
199      *   CharUtils.toIntValue('A')  throws IllegalArgumentException
200      * </pre>
201      *
202      * @param ch  the character to convert
203      * @return the int value of the character
204      * @throws IllegalArgumentException if the character is not ASCII numeric
205      */
toIntValue(final char ch)206     public static int toIntValue(final char ch) {
207         if (!isAsciiNumeric(ch)) {
208             throw new IllegalArgumentException("The character " + ch + " is not in the range '0' - '9'");
209         }
210         return ch - 48;
211     }
212 
213     /**
214      * Converts the character to the Integer it represents, throwing an
215      * exception if the character is not numeric.
216      *
217      * <p>This method converts the char '1' to the int 1 and so on.</p>
218      *
219      * <pre>
220      *   CharUtils.toIntValue('3', -1)  = 3
221      *   CharUtils.toIntValue('A', -1)  = -1
222      * </pre>
223      *
224      * @param ch  the character to convert
225      * @param defaultValue  the default value to use if the character is not numeric
226      * @return the int value of the character
227      */
toIntValue(final char ch, final int defaultValue)228     public static int toIntValue(final char ch, final int defaultValue) {
229         return isAsciiNumeric(ch) ? ch - 48 : defaultValue;
230     }
231 
232     /**
233      * Converts the character to the Integer it represents, throwing an
234      * exception if the character is not numeric.
235      *
236      * <p>This method converts the char '1' to the int 1 and so on.</p>
237      *
238      * <pre>
239      *   CharUtils.toIntValue('3')  = 3
240      *   CharUtils.toIntValue(null) throws IllegalArgumentException
241      *   CharUtils.toIntValue('A')  throws IllegalArgumentException
242      * </pre>
243      *
244      * @param ch  the character to convert, not null
245      * @return the int value of the character
246      * @throws NullPointerException if the Character is null
247      * @throws IllegalArgumentException if the Character is not ASCII numeric
248      */
toIntValue(final Character ch)249     public static int toIntValue(final Character ch) {
250         return toIntValue(toChar(ch));
251     }
252 
253     /**
254      * Converts the character to the Integer it represents, throwing an
255      * exception if the character is not numeric.
256      *
257      * <p>This method converts the char '1' to the int 1 and so on.</p>
258      *
259      * <pre>
260      *   CharUtils.toIntValue(null, -1) = -1
261      *   CharUtils.toIntValue('3', -1)  = 3
262      *   CharUtils.toIntValue('A', -1)  = -1
263      * </pre>
264      *
265      * @param ch  the character to convert
266      * @param defaultValue  the default value to use if the character is not numeric
267      * @return the int value of the character
268      */
toIntValue(final Character ch, final int defaultValue)269     public static int toIntValue(final Character ch, final int defaultValue) {
270         return ch != null ? toIntValue(ch.charValue(), defaultValue) : defaultValue;
271     }
272 
273     /**
274      * Converts the character to a String that contains the one character.
275      *
276      * <p>For ASCII 7 bit characters, this uses a cache that will return the
277      * same String object each time.</p>
278      *
279      * <pre>
280      *   CharUtils.toString(' ')  = " "
281      *   CharUtils.toString('A')  = "A"
282      * </pre>
283      *
284      * @param ch  the character to convert
285      * @return a String containing the one specified character
286      */
toString(final char ch)287     public static String toString(final char ch) {
288         if (ch < CHAR_STRING_ARRAY.length) {
289             return CHAR_STRING_ARRAY[ch];
290         }
291         return String.valueOf(ch);
292     }
293 
294     /**
295      * Converts the character to a String that contains the one character.
296      *
297      * <p>For ASCII 7 bit characters, this uses a cache that will return the
298      * same String object each time.</p>
299      *
300      * <p>If {@code null} is passed in, {@code null} will be returned.</p>
301      *
302      * <pre>
303      *   CharUtils.toString(null) = null
304      *   CharUtils.toString(' ')  = " "
305      *   CharUtils.toString('A')  = "A"
306      * </pre>
307      *
308      * @param ch  the character to convert
309      * @return a String containing the one specified character
310      */
toString(final Character ch)311     public static String toString(final Character ch) {
312         return ch != null ? toString(ch.charValue()) : null;
313     }
314 
315     /**
316      * Converts the string to the Unicode format '\u0020'.
317      *
318      * <p>This format is the Java source code format.</p>
319      *
320      * <pre>
321      *   CharUtils.unicodeEscaped(' ') = "\u0020"
322      *   CharUtils.unicodeEscaped('A') = "\u0041"
323      * </pre>
324      *
325      * @param ch  the character to convert
326      * @return the escaped Unicode string
327      */
unicodeEscaped(final char ch)328     public static String unicodeEscaped(final char ch) {
329         return "\\u" +
330             HEX_DIGITS[(ch >> 12) & 15] +
331             HEX_DIGITS[(ch >> 8) & 15] +
332             HEX_DIGITS[(ch >> 4) & 15] +
333             HEX_DIGITS[(ch) & 15];
334     }
335 
336     /**
337      * Converts the string to the Unicode format '\u0020'.
338      *
339      * <p>This format is the Java source code format.</p>
340      *
341      * <p>If {@code null} is passed in, {@code null} will be returned.</p>
342      *
343      * <pre>
344      *   CharUtils.unicodeEscaped(null) = null
345      *   CharUtils.unicodeEscaped(' ')  = "\u0020"
346      *   CharUtils.unicodeEscaped('A')  = "\u0041"
347      * </pre>
348      *
349      * @param ch  the character to convert, may be null
350      * @return the escaped Unicode string, null if null input
351      */
unicodeEscaped(final Character ch)352     public static String unicodeEscaped(final Character ch) {
353         return ch != null ? unicodeEscaped(ch.charValue()) : null;
354     }
355 
356     /**
357      * Checks whether the character is ASCII 7 bit.
358      *
359      * <pre>
360      *   CharUtils.isAscii('a')  = true
361      *   CharUtils.isAscii('A')  = true
362      *   CharUtils.isAscii('3')  = true
363      *   CharUtils.isAscii('-')  = true
364      *   CharUtils.isAscii('\n') = true
365      *   CharUtils.isAscii('&copy;') = false
366      * </pre>
367      *
368      * @param ch  the character to check
369      * @return true if less than 128
370      */
isAscii(final char ch)371     public static boolean isAscii(final char ch) {
372         return ch < 128;
373     }
374 
375     /**
376      * Checks whether the character is ASCII 7 bit printable.
377      *
378      * <pre>
379      *   CharUtils.isAsciiPrintable('a')  = true
380      *   CharUtils.isAsciiPrintable('A')  = true
381      *   CharUtils.isAsciiPrintable('3')  = true
382      *   CharUtils.isAsciiPrintable('-')  = true
383      *   CharUtils.isAsciiPrintable('\n') = false
384      *   CharUtils.isAsciiPrintable('&copy;') = false
385      * </pre>
386      *
387      * @param ch  the character to check
388      * @return true if between 32 and 126 inclusive
389      */
isAsciiPrintable(final char ch)390     public static boolean isAsciiPrintable(final char ch) {
391         return ch >= 32 && ch < 127;
392     }
393 
394     /**
395      * Checks whether the character is ASCII 7 bit control.
396      *
397      * <pre>
398      *   CharUtils.isAsciiControl('a')  = false
399      *   CharUtils.isAsciiControl('A')  = false
400      *   CharUtils.isAsciiControl('3')  = false
401      *   CharUtils.isAsciiControl('-')  = false
402      *   CharUtils.isAsciiControl('\n') = true
403      *   CharUtils.isAsciiControl('&copy;') = false
404      * </pre>
405      *
406      * @param ch  the character to check
407      * @return true if less than 32 or equals 127
408      */
isAsciiControl(final char ch)409     public static boolean isAsciiControl(final char ch) {
410         return ch < 32 || ch == 127;
411     }
412 
413     /**
414      * Checks whether the character is ASCII 7 bit alphabetic.
415      *
416      * <pre>
417      *   CharUtils.isAsciiAlpha('a')  = true
418      *   CharUtils.isAsciiAlpha('A')  = true
419      *   CharUtils.isAsciiAlpha('3')  = false
420      *   CharUtils.isAsciiAlpha('-')  = false
421      *   CharUtils.isAsciiAlpha('\n') = false
422      *   CharUtils.isAsciiAlpha('&copy;') = false
423      * </pre>
424      *
425      * @param ch  the character to check
426      * @return true if between 65 and 90 or 97 and 122 inclusive
427      */
isAsciiAlpha(final char ch)428     public static boolean isAsciiAlpha(final char ch) {
429         return isAsciiAlphaUpper(ch) || isAsciiAlphaLower(ch);
430     }
431 
432     /**
433      * Checks whether the character is ASCII 7 bit alphabetic upper case.
434      *
435      * <pre>
436      *   CharUtils.isAsciiAlphaUpper('a')  = false
437      *   CharUtils.isAsciiAlphaUpper('A')  = true
438      *   CharUtils.isAsciiAlphaUpper('3')  = false
439      *   CharUtils.isAsciiAlphaUpper('-')  = false
440      *   CharUtils.isAsciiAlphaUpper('\n') = false
441      *   CharUtils.isAsciiAlphaUpper('&copy;') = false
442      * </pre>
443      *
444      * @param ch  the character to check
445      * @return true if between 65 and 90 inclusive
446      */
isAsciiAlphaUpper(final char ch)447     public static boolean isAsciiAlphaUpper(final char ch) {
448         return ch >= 'A' && ch <= 'Z';
449     }
450 
451     /**
452      * Checks whether the character is ASCII 7 bit alphabetic lower case.
453      *
454      * <pre>
455      *   CharUtils.isAsciiAlphaLower('a')  = true
456      *   CharUtils.isAsciiAlphaLower('A')  = false
457      *   CharUtils.isAsciiAlphaLower('3')  = false
458      *   CharUtils.isAsciiAlphaLower('-')  = false
459      *   CharUtils.isAsciiAlphaLower('\n') = false
460      *   CharUtils.isAsciiAlphaLower('&copy;') = false
461      * </pre>
462      *
463      * @param ch  the character to check
464      * @return true if between 97 and 122 inclusive
465      */
isAsciiAlphaLower(final char ch)466     public static boolean isAsciiAlphaLower(final char ch) {
467         return ch >= 'a' && ch <= 'z';
468     }
469 
470     /**
471      * Checks whether the character is ASCII 7 bit numeric.
472      *
473      * <pre>
474      *   CharUtils.isAsciiNumeric('a')  = false
475      *   CharUtils.isAsciiNumeric('A')  = false
476      *   CharUtils.isAsciiNumeric('3')  = true
477      *   CharUtils.isAsciiNumeric('-')  = false
478      *   CharUtils.isAsciiNumeric('\n') = false
479      *   CharUtils.isAsciiNumeric('&copy;') = false
480      * </pre>
481      *
482      * @param ch  the character to check
483      * @return true if between 48 and 57 inclusive
484      */
isAsciiNumeric(final char ch)485     public static boolean isAsciiNumeric(final char ch) {
486         return ch >= '0' && ch <= '9';
487     }
488 
489     /**
490      * Checks whether the character is ASCII 7 bit numeric.
491      *
492      * <pre>
493      *   CharUtils.isAsciiAlphanumeric('a')  = true
494      *   CharUtils.isAsciiAlphanumeric('A')  = true
495      *   CharUtils.isAsciiAlphanumeric('3')  = true
496      *   CharUtils.isAsciiAlphanumeric('-')  = false
497      *   CharUtils.isAsciiAlphanumeric('\n') = false
498      *   CharUtils.isAsciiAlphanumeric('&copy;') = false
499      * </pre>
500      *
501      * @param ch  the character to check
502      * @return true if between 48 and 57 or 65 and 90 or 97 and 122 inclusive
503      */
isAsciiAlphanumeric(final char ch)504     public static boolean isAsciiAlphanumeric(final char ch) {
505         return isAsciiAlpha(ch) || isAsciiNumeric(ch);
506     }
507 
508     /**
509      * Compares two {@code char} values numerically. This is the same functionality as provided in Java 7.
510      *
511      * @param x the first {@code char} to compare
512      * @param y the second {@code char} to compare
513      * @return the value {@code 0} if {@code x == y};
514      *         a value less than {@code 0} if {@code x < y}; and
515      *         a value greater than {@code 0} if {@code x > y}
516      * @since 3.4
517      */
compare(final char x, final char y)518     public static int compare(final char x, final char y) {
519         return x - y;
520     }
521 }
522