All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.siashan.toolkit.crypt.util.StringUtils Maven / Gradle / Ivy

package com.siashan.toolkit.crypt.util;

import com.siashan.toolkit.crypt.binary.CharEncoding;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * 使用Java规范要求的编码将字符串与字节进行转换。这些编码是在
 * 标准字符集中指定。
 *
 * 

这个类是不可变的,并且是线程安全的.

* * @see CharEncoding * @see 标准字符集 * @author siashan * @since 1.0.7 */ public class StringUtils { public static final int INDEX_NOT_FOUND = -1; /** * 字符串常量:空字符串 {@code ""} */ public static final String EMPTY = ""; /** *

* 比较两个字符序列,如果它们表示相等的字符序列,则返回{@code true} *

* *

* {@code null}的处理没有异常。两个{@code null}引用被认为是相等的。比较是区分大小写的。 *

* *
     * StringUtils.equals(null, null)   = true
     * StringUtils.equals(null, "abc")  = false
     * StringUtils.equals("abc", null)  = false
     * StringUtils.equals("abc", "abc") = true
     * StringUtils.equals("abc", "ABC") = false
     * 
* * * @see Object#equals(Object) * @param cs1 * 第一个字符序列可以是{@code null} * @param cs2 * 第二个字符序列可以是{@code null} * @return {@code true}如果字符序列相等(区分大小写),或者两者都是{@code null} */ public static boolean equals(final CharSequence cs1, final CharSequence cs2) { if (cs1 == cs2) { return true; } if (cs1 == null || cs2 == null) { return false; } if (cs1 instanceof String && cs2 instanceof String) { return cs1.equals(cs2); } return cs1.length() == cs2.length() && CharSequenceUtils.regionMatches(cs1, false, 0, cs2, 0, cs1.length()); } /** * 判断字符串是否非空白字符串 * * @param str * @return */ public static boolean isNotBlank(CharSequence str){ return !isBlank(str); } /** * 判断字符串是否非空白字符串 * *
    *
  1. 不为 {@code null}
  2. *
  3. 不为空字符串:{@code ""}
  4. *
  5. 不为空格、全角空格、制表符、换行符,等不可见字符
  6. *
* * @param str 字符串 * @return 是否为空白字符串 */ public static boolean isBlank(CharSequence str){ int length; if ((str == null) || ((length = str.length()) == 0)) { return true; } for (int i = 0; i < length; i++) { // 只要有一个非空字符即为非空字符串 if (false == isBlankChar(str.charAt(i))) { return false; } } return true; } /** * 是否空白符
* 空白符包括空格、制表符、全角空格和不间断空格
* * @param c 字符 * @return 是否空白符 * @see Character#isWhitespace(int) * @see Character#isSpaceChar(int) */ public static boolean isBlankChar(char c) { return isBlankChar((int) c); } /** * 是否空白符
* 空白符包括空格、制表符、全角空格和不间断空格
* * @param c 字符 * @return 是否空白符 * @see Character#isWhitespace(int) * @see Character#isSpaceChar(int) */ public static boolean isBlankChar(int c) { return Character.isWhitespace(c) || Character.isSpaceChar(c) || c == '\ufeff' || c == '\u202a'; } /** * 调用 {@link String#getBytes(Charset)} * * @param string * 要编码的字符串(如果为null,则返回null)。 * @param charset * 用于编码{@code String}的{@link Charset} * @return 编码字节 */ private static ByteBuffer getByteBuffer(final String string, final Charset charset) { if (string == null) { return null; } return ByteBuffer.wrap(string.getBytes(charset)); } /** * 使用UTF-8字符集将给定字符串编码到字节缓冲区,并将结果存储到新的字节数组中。 * * @param string * 要编码的字符串可以是{@code null} * @return 编码字节,或{@code null}如果输入字符串为{@code null} */ public static ByteBuffer getByteBufferUtf8(final String string) { return getByteBuffer(string, StandardCharsets.UTF_8); } /** * 调用{@linkstring#getBytes(Charset)} * * @param string * 要编码的字符串(如果为null,则返回null)。 * @param charset * 用于编码{@code String}的{@link Charset} * @return 编码字节 */ public static byte[] getBytes(final String string, final Charset charset) { if (string == null) { return null; } return string.getBytes(charset); } /** * 使用ISO-8859-1字符集将给定字符串编码为字节序列,并将结果存储到新的字节数组中。 * * @param string * 要编码的字符串可以是{@code null} * @return 编码字节,或{@code null}如果输入字符串为{@code null} */ public static byte[] getBytesIso8859_1(final String string) { return getBytes(string, StandardCharsets.ISO_8859_1); } /** * 使用命名字符集将给定字符串编码为字节序列,并将结果存储到新的字节数组中 *

* 此方法捕获{@link UnsupportedEncodingException},并将其重新命名为{@link IllegalStateException},这 * 对于所需的字符集名称,不应发生这种情况。当编码需要在JRE中时,请使用此方法。 *

* * @param string * 要编码的字符串可以是{@code null} * @param charsetName * 所需的{@link Charset}的名称 * @return 编码字节,或{@code null}如果输入字符串为{@code null} */ public static byte[] getBytesUnchecked(final String string, final String charsetName) { if (string == null) { return null; } try { return string.getBytes(charsetName); } catch (final UnsupportedEncodingException e) { throw StringUtils.newIllegalStateException(charsetName, e); } } /** * 使用US-ASCII字符集将给定字符串编码为字节序列,并将结果存储到新的字节数组中。 * * @param string * 要编码的字符串可以是{@code null} * @return 编码字节,或{@code null}如果输入字符串为{@code null} */ public static byte[] getBytesUsAscii(final String string) { return getBytes(string, StandardCharsets.US_ASCII); } /** * 使用UTF-16字符集将给定字符串编码为字节序列,并将结果存储到新的字节数组中。 * * @param string * 要编码的字符串可以是{@code null} * @return 编码字节,或{@code null}如果输入字符串为{@code null} */ public static byte[] getBytesUtf16(final String string) { return getBytes(string, StandardCharsets.UTF_16); } /** * 使用UTF-16BE字符集将给定字符串编码为字节序列,并将结果存储到新的字节数组中。 * * @param string * 要编码的字符串可以是{@code null} * @return 编码字节,或{@code null}如果输入字符串为{@code null} */ public static byte[] getBytesUtf16Be(final String string) { return getBytes(string, StandardCharsets.UTF_16BE); } /** * 使用UTF-16LE字符集将给定字符串编码为字节序列,并将结果存储到新的字节数组中。 * * @param string * 要编码的字符串可以是{@code null} * @return 编码字节,或{@code null}如果输入字符串为{@code null} */ public static byte[] getBytesUtf16Le(final String string) { return getBytes(string, StandardCharsets.UTF_16LE); } /** * 使用UTF-8字符集将给定字符串编码为字节序列,并将结果存储到新的字节数组中。 * * @param string * 要编码的字符串可以是{@code null} * @return 编码字节,或{@code null}如果输入字符串为{@code null} */ public static byte[] getBytesUtf8(final String string) { return getBytes(string, StandardCharsets.UTF_8); } private static IllegalStateException newIllegalStateException(final String charsetName, final UnsupportedEncodingException e) { return new IllegalStateException(charsetName + ": " + e); } /** * 通过使用给定的字符集对指定的字节数组进行解码,构造一个新的{@code String}。 * * @param bytes * 要解码为字符的字节 * @param charset * {@link Charset}对{@code String}进行编码;非{@code null} * @return 使用给定的字符集从指定的字节数组解码的新{@code String},或者{@code null},如果输入字节数组为{@code null}。 */ public static String newString(final byte[] bytes, final Charset charset) { return bytes == null ? null : new String(bytes, charset); } /** * 通过使用给定的字符集对指定的字节数组进行解码,构造一个新的{@code String}. *

* 此方法捕获{@link UnsupportedEncodingException},并将其作为{@link IllegalStateException}重新抛出,这 * 对于所需的字符集名称,不应发生这种情况。当编码需要在JRE中时,请使用此方法。 *

* * @param bytes * 要解码为字符的字节可以是{@code null} * @param charsetName * 所需的{@link Charset}的名称 * @return 使用给定的字符集从指定的字节数组解码的新{@code String},或者{@code null},如果输入字节数组为{@code null}。 */ public static String newString(final byte[] bytes, final String charsetName) { if (bytes == null) { return null; } try { return new String(bytes, charsetName); } catch (final UnsupportedEncodingException e) { throw StringUtils.newIllegalStateException(charsetName, e); } } /** * 通过使用ISO-8859-1字符集对指定的字节数组进行解码,构造一个新的{@code String}。 * * @param bytes * 要解码为字符的字节可以是{@code null} * @return 使用ISO-8859-1字符集从指定的字节数组解码的新{@code String},或{@code null}如果输入字节数组为{@code null}。 */ public static String newStringIso8859_1(final byte[] bytes) { return newString(bytes, StandardCharsets.ISO_8859_1); } /** * 通过使用US-ASCII字符集对指定的字节数组进行解码,构造一个新的{@code String}。 * * @param bytes * 要解码为字符的字节 * @return 使用US-ASCII字符集从指定的字节数组解码的新{@code String},或者{@code null},如果输入字节数组为{@code null}。 */ public static String newStringUsAscii(final byte[] bytes) { return newString(bytes, StandardCharsets.US_ASCII); } /** * 通过使用UTF-16字符集对指定的字节数组进行解码,构造一个新的{@code String}。 * * @param bytes * 要解码为字符的字节 * @return 使用UTF-16字符集从指定的字节数组解码的新{@code String}或者{@code null},如果输入字节数组为{@code null}。 */ public static String newStringUtf16(final byte[] bytes) { return newString(bytes, StandardCharsets.UTF_16); } /** * 通过使用UTF-16BE字符集对指定的字节数组进行解码,构造一个新的{@code String}。 * * @param bytes * 要解码为字符的字节 * @return 使用UTF-16BE字符集从指定的字节数组解码的新{@code String},或者{@code null},如果输入字节数组为{@code null}。 */ public static String newStringUtf16Be(final byte[] bytes) { return newString(bytes, StandardCharsets.UTF_16BE); } /** * 通过使用UTF-16LE字符集对指定的字节数组进行解码,构造一个新的{@code String}。 * * @param bytes * 要解码为字符的字节 * @return 使用UTF-16LE字符集从指定的字节数组解码的新{@code String},或者{@code null}如果输入字节数组是{@code null}. */ public static String newStringUtf16Le(final byte[] bytes) { return newString(bytes, StandardCharsets.UTF_16LE); } /** * 通过使用UTF-8字符集对指定的字节数组进行解码,构造一个新的{@code String} * * @param bytes * 要解码为字符的字节 * @return 使用UTF-8字符集从指定的字节数组解码的新{@code String},或者{@code null},如果输入字节数组为{@code null}。 */ public static String newStringUtf8(final byte[] bytes) { return newString(bytes, StandardCharsets.UTF_8); } /** * 是否以指定字符串开头,忽略大小写 * * @param str 被监测字符串 * @param prefix 开头字符串 * @return 是否以指定字符串开头 */ public static boolean startWithIgnoreCase(CharSequence str, CharSequence prefix) { return startWith(str, prefix, true); } /** * 指定范围内查找字符串,忽略大小写 * * @param str 字符串 * @param searchStr 需要查找位置的字符串 * @return 位置 */ public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { return lastIndexOfIgnoreCase(str, searchStr, str.length()); } /** * 指定范围内查找字符串,忽略大小写
* fromIndex 为搜索起始位置,从后往前计数 * * @param str 字符串 * @param searchStr 需要查找位置的字符串 * @param fromIndex 起始位置,从后往前计数 * @return 位置 */ public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int fromIndex) { return lastIndexOf(str, searchStr, fromIndex, true); } /** * 指定范围内查找字符串
* fromIndex 为搜索起始位置,从后往前计数 * * @param str 字符串 * @param searchStr 需要查找位置的字符串 * @param fromIndex 起始位置,从后往前计数 * @param ignoreCase 是否忽略大小写 * @return 位置 */ public static int lastIndexOf(final CharSequence str, final CharSequence searchStr, int fromIndex, boolean ignoreCase) { if (str == null || searchStr == null) { return INDEX_NOT_FOUND; } if (fromIndex < 0) { fromIndex = 0; } fromIndex = Math.min(fromIndex, str.length()); if (searchStr.length() == 0) { return fromIndex; } if (false == ignoreCase) { // 不忽略大小写调用JDK方法 return str.toString().lastIndexOf(searchStr.toString(), fromIndex); } for (int i = fromIndex; i >= 0; i--) { if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) { return i; } } return INDEX_NOT_FOUND; } /** * 截取两个字符串的不同部分(长度一致),判断截取的子串是否相同
* 任意一个字符串为null返回false * * @param str1 第一个字符串 * @param start1 第一个字符串开始的位置 * @param str2 第二个字符串 * @param start2 第二个字符串开始的位置 * @param length 截取长度 * @param ignoreCase 是否忽略大小写 * @return 子串是否相同 */ public static boolean isSubEquals(CharSequence str1, int start1, CharSequence str2, int start2, int length, boolean ignoreCase) { if (null == str1 || null == str2) { return false; } return str1.toString().regionMatches(ignoreCase, start1, str2.toString(), start2, length); } /** * 是否以指定字符串开头
* 如果给定的字符串和开头字符串都为null则返回true,否则任意一个值为null返回false * * @param str 被监测字符串 * @param prefix 开头字符串 * @param ignoreCase 是否忽略大小写 * @return 是否以指定字符串开头 */ public static boolean startWith(CharSequence str, CharSequence prefix, boolean ignoreCase) { return startWith(str, prefix, ignoreCase, false); } /** * 是否以指定字符串开头
* 如果给定的字符串和开头字符串都为null则返回true,否则任意一个值为null返回false * * @param str 被监测字符串 * @param prefix 开头字符串 * @param ignoreCase 是否忽略大小写 * @param ignoreEquals 是否忽略字符串相等的情况 * @return 是否以指定字符串开头 */ public static boolean startWith(CharSequence str, CharSequence prefix, boolean ignoreCase, boolean ignoreEquals) { if (null == str || null == prefix) { if (false == ignoreEquals) { return false; } return null == str && null == prefix; } boolean isStartWith; if (ignoreCase) { isStartWith = str.toString().toLowerCase().startsWith(prefix.toString().toLowerCase()); } else { isStartWith = str.toString().startsWith(prefix.toString()); } if (isStartWith) { return (false == ignoreEquals) || (false == equals(str, prefix, ignoreCase)); } return false; } /** * 比较两个字符串是否相等。 * * @param str1 要比较的字符串1 * @param str2 要比较的字符串2 * @param ignoreCase 是否忽略大小写 * @return 如果两个字符串相同,或者都是{@code null},则返回{@code true} */ public static boolean equals(CharSequence str1, CharSequence str2, boolean ignoreCase) { if (null == str1) { // 只有两个都为null才判断相等 return str2 == null; } if (null == str2) { // 字符串2空,字符串1非空,直接false return false; } if (ignoreCase) { return str1.toString().equalsIgnoreCase(str2.toString()); } else { return str1.toString().contentEquals(str2); } } /** * 切割指定位置之后部分的字符串 * * @param string 字符串 * @param fromIndex 切割开始的位置(包括) * @return 切割后后剩余的后半部分字符串 */ public static String subSuf(CharSequence string, int fromIndex) { if (isEmpty(string)) { return null; } return sub(string, fromIndex, string.length()); } /** *

字符串是否为空,空的定义如下:

*
    *
  1. {@code null}
  2. *
  3. 空字符串:{@code ""}
  4. *
* *

例:

*
    *
  • {@code StrUtil.isEmpty(null) // true}
  • *
  • {@code StrUtil.isEmpty("") // true}
  • *
  • {@code StrUtil.isEmpty(" \t\n") // false}
  • *
  • {@code StrUtil.isEmpty("abc") // false}
  • *
* *

注意:该方法与 {@link #isBlank(CharSequence)} 的区别是:该方法不校验空白字符。

*

建议:

* * @param str 被检测的字符串 * @return 是否为空 * @see #isBlank(CharSequence) */ public static boolean isEmpty(CharSequence str) { return str == null || str.length() == 0; } /** * 改进JDK subString
* index从0开始计算,最后一个字符为-1
* 如果from和to位置一样,返回 ""
* 如果from或to为负数,则按照length从后向前数位置,如果绝对值大于字符串长度,则from归到0,to归到length
* 如果经过修正的index中from大于to,则互换from和to example:
* abcdefgh 2 3 =》 c
* abcdefgh 2 -3 =》 cde
* * @param str String * @param fromIndexInclude 开始的index(包括) * @param toIndexExclude 结束的index(不包括) * @return 字串 */ public static String sub(CharSequence str, int fromIndexInclude, int toIndexExclude) { if (isEmpty(str)) { return str(str); } int len = str.length(); if (fromIndexInclude < 0) { fromIndexInclude = len + fromIndexInclude; if (fromIndexInclude < 0) { fromIndexInclude = 0; } } else if (fromIndexInclude > len) { fromIndexInclude = len; } if (toIndexExclude < 0) { toIndexExclude = len + toIndexExclude; if (toIndexExclude < 0) { toIndexExclude = len; } } else if (toIndexExclude > len) { toIndexExclude = len; } if (toIndexExclude < fromIndexInclude) { int tmp = fromIndexInclude; fromIndexInclude = toIndexExclude; toIndexExclude = tmp; } if (fromIndexInclude == toIndexExclude) { return EMPTY; } return str.toString().substring(fromIndexInclude, toIndexExclude); } /** * {@link CharSequence} 转为字符串,null安全 * * @param cs {@link CharSequence} * @return 字符串 */ public static String str(CharSequence cs) { return null == cs ? null : cs.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy