001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3; 018 019import java.util.Objects; 020 021/** 022 * Operations on char primitives and Character objects. 023 * 024 * <p> 025 * This class tries to handle {@code null} input gracefully. 026 * An exception will not be thrown for a {@code null} input. 027 * Each method documents its behavior in more detail. 028 * </p> 029 * 030 * <p> 031 * #ThreadSafe# 032 * </p> 033 * 034 * @since 2.1 035 */ 036public class CharUtils { 037 038 private static final String[] CHAR_STRING_ARRAY = ArrayUtils.setAll(new String[128], i -> String.valueOf((char) i)); 039 040 private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 041 042 /** 043 * Linefeed character LF ({@code '\n'}, Unicode 000a). 044 * 045 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 046 * for Character and String Literals</a> 047 * @since 2.2 048 */ 049 public static final char LF = '\n'; 050 051 /** 052 * Carriage return character CR ('\r', Unicode 000d). 053 * 054 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences 055 * for Character and String Literals</a> 056 * @since 2.2 057 */ 058 public static final char CR = '\r'; 059 060 /** 061 * {@code \u0000} null control character ('\0'), abbreviated NUL. 062 * 063 * @since 3.6 064 */ 065 public static final char NUL = '\0'; 066 067 /** 068 * Compares two {@code char} values numerically. This is the same functionality as provided in Java 7. 069 * 070 * @param x The first {@code char} to compare 071 * @param y The second {@code char} to compare 072 * @return The value {@code 0} if {@code x == y}; 073 * a value less than {@code 0} if {@code x < y}; and 074 * a value greater than {@code 0} if {@code x > y} 075 * @since 3.4 076 */ 077 public static int compare(final char x, final char y) { 078 return x - y; 079 } 080 081 /** 082 * Tests whether the character is ASCII 7 bit. 083 * 084 * <pre> 085 * CharUtils.isAscii('a') = true 086 * CharUtils.isAscii('A') = true 087 * CharUtils.isAscii('3') = true 088 * CharUtils.isAscii('-') = true 089 * CharUtils.isAscii('\n') = true 090 * CharUtils.isAscii('©') = false 091 * </pre> 092 * 093 * @param ch The character to check 094 * @return true if less than 128 095 */ 096 public static boolean isAscii(final char ch) { 097 return ch < 128; 098 } 099 100 /** 101 * Tests whether the character is ASCII 7 bit alphabetic. 102 * 103 * <pre> 104 * CharUtils.isAsciiAlpha('a') = true 105 * CharUtils.isAsciiAlpha('A') = true 106 * CharUtils.isAsciiAlpha('3') = false 107 * CharUtils.isAsciiAlpha('-') = false 108 * CharUtils.isAsciiAlpha('\n') = false 109 * CharUtils.isAsciiAlpha('©') = false 110 * </pre> 111 * 112 * @param ch The character to check 113 * @return true if between 65 and 90 or 97 and 122 inclusive 114 */ 115 public static boolean isAsciiAlpha(final char ch) { 116 return isAsciiAlphaUpper(ch) || isAsciiAlphaLower(ch); 117 } 118 119 /** 120 * Tests whether the character is ASCII 7 bit alphabetic lower case. 121 * 122 * <pre> 123 * CharUtils.isAsciiAlphaLower('a') = true 124 * CharUtils.isAsciiAlphaLower('A') = false 125 * CharUtils.isAsciiAlphaLower('3') = false 126 * CharUtils.isAsciiAlphaLower('-') = false 127 * CharUtils.isAsciiAlphaLower('\n') = false 128 * CharUtils.isAsciiAlphaLower('©') = false 129 * </pre> 130 * 131 * @param ch The character to check 132 * @return true if between 97 and 122 inclusive 133 */ 134 public static boolean isAsciiAlphaLower(final char ch) { 135 return ch >= 'a' && ch <= 'z'; 136 } 137 138 /** 139 * Tests whether the character is ASCII 7 bit alphanumeric character. 140 * 141 * <pre> 142 * CharUtils.isAsciiAlphanumeric('a') = true 143 * CharUtils.isAsciiAlphanumeric('A') = true 144 * CharUtils.isAsciiAlphanumeric('3') = true 145 * CharUtils.isAsciiAlphanumeric('-') = false 146 * CharUtils.isAsciiAlphanumeric('\n') = false 147 * CharUtils.isAsciiAlphanumeric('©') = false 148 * </pre> 149 * 150 * @param ch The character to check 151 * @return true if between 48 and 57 or 65 and 90 or 97 and 122 inclusive 152 */ 153 public static boolean isAsciiAlphanumeric(final char ch) { 154 return isAsciiAlpha(ch) || isAsciiNumeric(ch); 155 } 156 157 /** 158 * Tests whether the character is ASCII 7 bit alphabetic upper case. 159 * 160 * <pre> 161 * CharUtils.isAsciiAlphaUpper('a') = false 162 * CharUtils.isAsciiAlphaUpper('A') = true 163 * CharUtils.isAsciiAlphaUpper('3') = false 164 * CharUtils.isAsciiAlphaUpper('-') = false 165 * CharUtils.isAsciiAlphaUpper('\n') = false 166 * CharUtils.isAsciiAlphaUpper('©') = false 167 * </pre> 168 * 169 * @param ch The character to check 170 * @return true if between 65 and 90 inclusive 171 */ 172 public static boolean isAsciiAlphaUpper(final char ch) { 173 return ch >= 'A' && ch <= 'Z'; 174 } 175 176 /** 177 * Tests whether the character is ASCII 7 bit control. 178 * 179 * <pre> 180 * CharUtils.isAsciiControl('a') = false 181 * CharUtils.isAsciiControl('A') = false 182 * CharUtils.isAsciiControl('3') = false 183 * CharUtils.isAsciiControl('-') = false 184 * CharUtils.isAsciiControl('\n') = true 185 * CharUtils.isAsciiControl('©') = false 186 * </pre> 187 * 188 * @param ch The character to check 189 * @return true if less than 32 or equals 127 190 */ 191 public static boolean isAsciiControl(final char ch) { 192 return ch < 32 || ch == 127; 193 } 194 195 /** 196 * Tests whether the character is ASCII 7 bit numeric. 197 * 198 * <pre> 199 * CharUtils.isAsciiNumeric('a') = false 200 * CharUtils.isAsciiNumeric('A') = false 201 * CharUtils.isAsciiNumeric('3') = true 202 * CharUtils.isAsciiNumeric('-') = false 203 * CharUtils.isAsciiNumeric('\n') = false 204 * CharUtils.isAsciiNumeric('©') = false 205 * </pre> 206 * 207 * @param ch The character to check 208 * @return true if between 48 and 57 inclusive 209 */ 210 public static boolean isAsciiNumeric(final char ch) { 211 return ch >= '0' && ch <= '9'; 212 } 213 214 /** 215 * Tests whether the character is ASCII 7 bit numeric. 216 * 217 * <pre> 218 * CharUtils.isAsciiNumeric('a') = false 219 * CharUtils.isAsciiNumeric('A') = false 220 * CharUtils.isAsciiNumeric('3') = true 221 * CharUtils.isAsciiNumeric('-') = false 222 * CharUtils.isAsciiNumeric('\n') = false 223 * CharUtils.isAsciiNumeric('©') = false 224 * </pre> 225 * 226 * @param ch The code point to check. 227 * @return true if between 48 and 57 inclusive. 228 * @since 3.21.0 229 */ 230 public static boolean isAsciiNumeric(final int ch) { 231 return ch >= '0' && ch <= '9'; 232 } 233 234 /** 235 * Tests whether the character is ASCII 7 bit printable. 236 * 237 * <pre> 238 * CharUtils.isAsciiPrintable('a') = true 239 * CharUtils.isAsciiPrintable('A') = true 240 * CharUtils.isAsciiPrintable('3') = true 241 * CharUtils.isAsciiPrintable('-') = true 242 * CharUtils.isAsciiPrintable('\n') = false 243 * CharUtils.isAsciiPrintable('©') = false 244 * </pre> 245 * 246 * @param ch The character to check 247 * @return true if between 32 and 126 inclusive 248 */ 249 public static boolean isAsciiPrintable(final char ch) { 250 return ch >= 32 && ch < 127; 251 } 252 253 /** 254 * Tests whether a character is a hexadecimal character. 255 * 256 * <pre> 257 * CharUtils.isHex('0') = true 258 * CharUtils.isHex('3') = true 259 * CharUtils.isHex('9') = true 260 * CharUtils.isHex('a') = true 261 * CharUtils.isHex('f') = true 262 * CharUtils.isHex('g') = false 263 * CharUtils.isHex('A') = true 264 * CharUtils.isHex('F') = true 265 * CharUtils.isHex('G') = false 266 * CharUtils.isHex('#') = false 267 * CharUtils.isHex('-') = false 268 * CharUtils.isHex('\n') = false 269 * CharUtils.isHex('©') = false 270 * </pre> 271 * 272 * @param ch The character to test. 273 * @return true if character is a hexadecimal character. 274 * @since 3.18.0 275 */ 276 public static boolean isHex(final char ch) { 277 return isAsciiNumeric(ch) || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F'; 278 } 279 280 /** 281 * Tests whether a character is a hexadecimal character. 282 * 283 * <pre> 284 * CharUtils.isHex('0') = true 285 * CharUtils.isHex('3') = true 286 * CharUtils.isHex('9') = true 287 * CharUtils.isHex('a') = true 288 * CharUtils.isHex('f') = true 289 * CharUtils.isHex('g') = false 290 * CharUtils.isHex('A') = true 291 * CharUtils.isHex('F') = true 292 * CharUtils.isHex('G') = false 293 * CharUtils.isHex('#') = false 294 * CharUtils.isHex('-') = false 295 * CharUtils.isHex('\n') = false 296 * CharUtils.isHex('©') = false 297 * </pre> 298 * 299 * @param ch The code point to test. 300 * @return true if character is a hexadecimal character. 301 * @since 3.21.0 302 */ 303 public static boolean isHex(final int ch) { 304 return isAsciiNumeric(ch) || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F'; 305 } 306 307 /** 308 * Tests if the given char is an octal digit. Octal digits are the character representations of the digits 0 to 7. 309 * 310 * @param ch The byte to check. 311 * @return true if the given char is the character representation of one of the digits from 0 to 7. 312 * @since 3.21.0 313 */ 314 public static boolean isOctal(final byte ch) { 315 return ch >= '0' && ch <= '7'; 316 } 317 318 /** 319 * Tests if the given char is an octal digit. Octal digits are the character representations of the digits 0 to 7. 320 * 321 * @param ch The char to check. 322 * @return true if the given char is the character representation of one of the digits from 0 to 7. 323 * @since 3.18.0 324 */ 325 public static boolean isOctal(final char ch) { 326 return ch >= '0' && ch <= '7'; 327 } 328 329 /** 330 * Converts the Character to a char throwing an exception for {@code null}. 331 * 332 * <pre> 333 * CharUtils.toChar(' ') = ' ' 334 * CharUtils.toChar('A') = 'A' 335 * CharUtils.toChar(null) throws NullPointerException 336 * </pre> 337 * 338 * @param ch The character to convert 339 * @return The char value of the Character 340 * @throws NullPointerException Thrown if the Character is null. 341 */ 342 public static char toChar(final Character ch) { 343 return Objects.requireNonNull(ch, "ch").charValue(); 344 } 345 346 /** 347 * Converts the Character to a char handling {@code null}. 348 * 349 * <pre> 350 * CharUtils.toChar(null, 'X') = 'X' 351 * CharUtils.toChar(' ', 'X') = ' ' 352 * CharUtils.toChar('A', 'X') = 'A' 353 * </pre> 354 * 355 * @param ch The character to convert 356 * @param defaultValue The value to use if the Character is null 357 * @return The char value of the Character or the default if null 358 */ 359 public static char toChar(final Character ch, final char defaultValue) { 360 return ch != null ? ch.charValue() : defaultValue; 361 } 362 363 /** 364 * Converts the String to a char using the first character, throwing 365 * an exception on empty Strings. 366 * 367 * <pre> 368 * CharUtils.toChar("A") = 'A' 369 * CharUtils.toChar("BA") = 'B' 370 * CharUtils.toChar(null) throws NullPointerException 371 * CharUtils.toChar("") throws IllegalArgumentException 372 * </pre> 373 * 374 * @param str The character to convert 375 * @return The char value of the first letter of the String 376 * @throws NullPointerException Thrown if the string is null. 377 * @throws IllegalArgumentException Thrown if the String is empty. 378 */ 379 public static char toChar(final String str) { 380 Validate.notEmpty(str, "The String must not be empty"); 381 return str.charAt(0); 382 } 383 384 /** 385 * Converts the String to a char using the first character, defaulting 386 * the value on empty Strings. 387 * 388 * <pre> 389 * CharUtils.toChar(null, 'X') = 'X' 390 * CharUtils.toChar("", 'X') = 'X' 391 * CharUtils.toChar("A", 'X') = 'A' 392 * CharUtils.toChar("BA", 'X') = 'B' 393 * </pre> 394 * 395 * @param str The character to convert 396 * @param defaultValue The value to use if the Character is null 397 * @return The char value of the first letter of the String or the default if null 398 */ 399 public static char toChar(final String str, final char defaultValue) { 400 return StringUtils.isEmpty(str) ? defaultValue : str.charAt(0); 401 } 402 403 /** 404 * Delegates to {@link Character#valueOf(char)}. 405 * 406 * @param c The character to convert 407 * @return A {@code Character} representing {@code c}. 408 * @deprecated Use {@link Character#valueOf(char)}. 409 */ 410 @Deprecated 411 public static Character toCharacterObject(final char c) { 412 return Character.valueOf(c); 413 } 414 415 /** 416 * Converts the String to a Character using the first character, returning 417 * null for empty Strings. 418 * 419 * <p> 420 * For ASCII 7 bit characters, this uses a cache that will return the 421 * same Character object each time. 422 * </p> 423 * 424 * <pre> 425 * CharUtils.toCharacterObject(null) = null 426 * CharUtils.toCharacterObject("") = null 427 * CharUtils.toCharacterObject("A") = 'A' 428 * CharUtils.toCharacterObject("BA") = 'B' 429 * </pre> 430 * 431 * @param str The character to convert 432 * @return The Character value of the first letter of the String 433 */ 434 public static Character toCharacterObject(final String str) { 435 return StringUtils.isEmpty(str) ? null : Character.valueOf(str.charAt(0)); 436 } 437 438 /** 439 * Converts the character to the Integer it represents, throwing an 440 * exception if the character is not numeric. 441 * 442 * <p> 443 * This method converts the char '1' to the int 1 and so on. 444 * </p> 445 * 446 * <pre> 447 * CharUtils.toIntValue('3') = 3 448 * CharUtils.toIntValue('A') throws IllegalArgumentException 449 * </pre> 450 * 451 * @param ch The character to convert 452 * @return The int value of the character 453 * @throws IllegalArgumentException Thrown if the character is not ASCII numeric. 454 */ 455 public static int toIntValue(final char ch) { 456 if (!isAsciiNumeric(ch)) { 457 throw new IllegalArgumentException("The character " + ch + " is not in the range '0' - '9'"); 458 } 459 return ch - 48; 460 } 461 462 /** 463 * Converts the character to the Integer it represents, throwing an 464 * exception if the character is not numeric. 465 * 466 * <p> 467 * This method converts the char '1' to the int 1 and so on. 468 * </p> 469 * 470 * <pre> 471 * CharUtils.toIntValue('3', -1) = 3 472 * CharUtils.toIntValue('A', -1) = -1 473 * </pre> 474 * 475 * @param ch The character to convert 476 * @param defaultValue The default value to use if the character is not numeric 477 * @return The int value of the character 478 */ 479 public static int toIntValue(final char ch, final int defaultValue) { 480 return isAsciiNumeric(ch) ? ch - 48 : defaultValue; 481 } 482 483 /** 484 * Converts the character to the Integer it represents, throwing an 485 * exception if the character is not numeric. 486 * 487 * <p> 488 * This method converts the char '1' to the int 1 and so on. 489 * </p> 490 * 491 * <pre> 492 * CharUtils.toIntValue('3') = 3 493 * CharUtils.toIntValue(null) throws NullPointerException 494 * CharUtils.toIntValue('A') throws IllegalArgumentException 495 * </pre> 496 * 497 * @param ch The character to convert, not null 498 * @return The int value of the character 499 * @throws NullPointerException Thrown if the Character is null. 500 * @throws IllegalArgumentException Thrown if the Character is not ASCII numeric. 501 */ 502 public static int toIntValue(final Character ch) { 503 return toIntValue(toChar(ch)); 504 } 505 506 /** 507 * Converts the character to the Integer it represents, throwing an 508 * exception if the character is not numeric. 509 * 510 * <p> 511 * This method converts the char '1' to the int 1 and so on. 512 * </p> 513 * 514 * <pre> 515 * CharUtils.toIntValue(null, -1) = -1 516 * CharUtils.toIntValue('3', -1) = 3 517 * CharUtils.toIntValue('A', -1) = -1 518 * </pre> 519 * 520 * @param ch The character to convert 521 * @param defaultValue The default value to use if the character is not numeric 522 * @return The int value of the character 523 */ 524 public static int toIntValue(final Character ch, final int defaultValue) { 525 return ch != null ? toIntValue(ch.charValue(), defaultValue) : defaultValue; 526 } 527 528 /** 529 * Converts the character to a String that contains the one character. 530 * 531 * <p> 532 * For ASCII 7 bit characters, this uses a cache that will return the 533 * same String object each time. 534 * </p> 535 * 536 * <pre> 537 * CharUtils.toString(' ') = " " 538 * CharUtils.toString('A') = "A" 539 * </pre> 540 * 541 * @param ch The character to convert 542 * @return A String containing the one specified character 543 */ 544 public static String toString(final char ch) { 545 if (ch < CHAR_STRING_ARRAY.length) { 546 return CHAR_STRING_ARRAY[ch]; 547 } 548 return String.valueOf(ch); 549 } 550 551 /** 552 * Converts the character to a String that contains the one character. 553 * 554 * <p> 555 * For ASCII 7 bit characters, this uses a cache that will return the 556 * same String object each time. 557 * </p> 558 * 559 * <p> 560 * If {@code null} is passed in, {@code null} will be returned. 561 * </p> 562 * 563 * <pre> 564 * CharUtils.toString(null) = null 565 * CharUtils.toString(' ') = " " 566 * CharUtils.toString('A') = "A" 567 * </pre> 568 * 569 * @param ch The character to convert 570 * @return A String containing the one specified character 571 */ 572 public static String toString(final Character ch) { 573 return ch != null ? toString(ch.charValue()) : null; 574 } 575 576 /** 577 * Converts the string to the Unicode format '\u0020'. 578 * 579 * <p> 580 * This format is the Java source code format. 581 * </p> 582 * 583 * <pre> 584 * CharUtils.unicodeEscaped(' ') = "\u0020" 585 * CharUtils.unicodeEscaped('A') = "\u0041" 586 * </pre> 587 * 588 * @param ch The character to convert 589 * @return The escaped Unicode string 590 */ 591 public static String unicodeEscaped(final char ch) { 592 return "\\u" + 593 HEX_DIGITS[ch >> 12 & 15] + 594 HEX_DIGITS[ch >> 8 & 15] + 595 HEX_DIGITS[ch >> 4 & 15] + 596 HEX_DIGITS[ch & 15]; 597 } 598 599 /** 600 * Converts the string to the Unicode format '\u0020'. 601 * 602 * <p> 603 * This format is the Java source code format. 604 * </p> 605 * 606 * <p> 607 * If {@code null} is passed in, {@code null} will be returned. 608 * </p> 609 * 610 * <pre> 611 * CharUtils.unicodeEscaped(null) = null 612 * CharUtils.unicodeEscaped(' ') = "\u0020" 613 * CharUtils.unicodeEscaped('A') = "\u0041" 614 * </pre> 615 * 616 * @param ch The character to convert, may be null 617 * @return The escaped Unicode string, null if null input 618 */ 619 public static String unicodeEscaped(final Character ch) { 620 return ch != null ? unicodeEscaped(ch.charValue()) : null; 621 } 622 623 /** 624 * {@link CharUtils} instances should NOT be constructed in standard programming. 625 * Instead, the class should be used as {@code CharUtils.toString('c');}. 626 * 627 * <p> 628 * This constructor is public to permit tools that require a JavaBean instance 629 * to operate. 630 * </p> 631 * 632 * @deprecated TODO Make private in 4.0. 633 */ 634 @Deprecated 635 public CharUtils() { 636 // empty 637 } 638}