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