This commit is contained in:
Looly 2023-03-25 14:52:54 +08:00
parent c20a2ff710
commit 8ae651caed
7 changed files with 166 additions and 56 deletions

View File

@ -5,6 +5,7 @@ import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.SafeConcurrentHashMap; import cn.hutool.core.map.SafeConcurrentHashMap;
import cn.hutool.core.text.CharPool; import cn.hutool.core.text.CharPool;
import cn.hutool.core.text.StrTrimer;
import cn.hutool.core.text.StrUtil; import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.CharUtil;
@ -292,7 +293,7 @@ public class ClassLoaderUtil {
*/ */
private static Class<?> doLoadClass(String name, final boolean isInitialized, final ClassLoader classLoader) { private static Class<?> doLoadClass(String name, final boolean isInitialized, final ClassLoader classLoader) {
// 去除尾部多余的"." // 去除尾部多余的"."
name = StrUtil.trim(name, 1, (c) -> CharUtil.DOT == c); name = StrUtil.trim(name, StrTrimer.TrimMode.SUFFIX, (c) -> CharUtil.DOT == c);
Class<?> clazz; Class<?> clazz;
if (name.endsWith(ARRAY_SUFFIX)) { if (name.endsWith(ARRAY_SUFFIX)) {
// 对象数组"java.lang.String[]"风格 // 对象数组"java.lang.String[]"风格

View File

@ -360,7 +360,7 @@ public class FileNameUtil {
// 统一使用斜杠 // 统一使用斜杠
pathToUse = pathToUse.replaceAll("[/\\\\]+", StrUtil.SLASH); pathToUse = pathToUse.replaceAll("[/\\\\]+", StrUtil.SLASH);
// 去除开头空白符末尾空白符合法不去除 // 去除开头空白符末尾空白符合法不去除
pathToUse = StrUtil.trimStart(pathToUse); pathToUse = StrUtil.trimPrefix(pathToUse);
//兼容Windows下的共享目录路径原始路径如果以\\开头则保留这种路径 //兼容Windows下的共享目录路径原始路径如果以\\开头则保留这种路径
if (path.startsWith("\\\\")) { if (path.startsWith("\\\\")) {
pathToUse = "\\" + pathToUse; pathToUse = "\\" + pathToUse;

View File

@ -107,7 +107,7 @@ public final class UrlBuilder implements Builder<String> {
public static UrlBuilder ofHttp(String httpUrl, final Charset charset) { public static UrlBuilder ofHttp(String httpUrl, final Charset charset) {
Assert.notBlank(httpUrl, "Http url must be not blank!"); Assert.notBlank(httpUrl, "Http url must be not blank!");
httpUrl = StrUtil.trimStart(httpUrl); httpUrl = StrUtil.trimPrefix(httpUrl);
// issue#I66CIR // issue#I66CIR
if(false == StrUtil.startWithAnyIgnoreCase(httpUrl, "http://", "https://")){ if(false == StrUtil.startWithAnyIgnoreCase(httpUrl, "http://", "https://")){
httpUrl = "http://" + httpUrl; httpUrl = "http://" + httpUrl;

View File

@ -177,7 +177,7 @@ public class CharSequenceUtil extends StrChecker {
* @return 除去头尾空白的字符串如果原字串为{@code null}则返回{@code null} * @return 除去头尾空白的字符串如果原字串为{@code null}则返回{@code null}
*/ */
public static String trim(final CharSequence str) { public static String trim(final CharSequence str) {
return (null == str) ? null : trim(str, 0); return StrTrimer.TRIM_BLANK.apply(str);
} }
/** /**
@ -226,19 +226,19 @@ public class CharSequenceUtil extends StrChecker {
* 注意{@link String#trim()}不同此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白 因而可以除去英文字符集之外的其它空白如中文空格 * 注意{@link String#trim()}不同此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白 因而可以除去英文字符集之外的其它空白如中文空格
* *
* <pre> * <pre>
* trimStart(null) = null * trimPrefix(null) = null
* trimStart(&quot;&quot;) = &quot;&quot; * trimPrefix(&quot;&quot;) = &quot;&quot;
* trimStart(&quot;abc&quot;) = &quot;abc&quot; * trimPrefix(&quot;abc&quot;) = &quot;abc&quot;
* trimStart(&quot; abc&quot;) = &quot;abc&quot; * trimPrefix(&quot; abc&quot;) = &quot;abc&quot;
* trimStart(&quot;abc &quot;) = &quot;abc &quot; * trimPrefix(&quot;abc &quot;) = &quot;abc &quot;
* trimStart(&quot; abc &quot;) = &quot;abc &quot; * trimPrefix(&quot; abc &quot;) = &quot;abc &quot;
* </pre> * </pre>
* *
* @param str 要处理的字符串 * @param str 要处理的字符串
* @return 除去空白的字符串如果原字串为{@code null}或结果字符串为{@code ""}则返回 {@code null} * @return 除去空白的字符串如果原字串为{@code null}或结果字符串为{@code ""}则返回 {@code null}
*/ */
public static String trimStart(final CharSequence str) { public static String trimPrefix(final CharSequence str) {
return trim(str, -1); return StrTrimer.TRIM_PREFIX_BLANK.apply(str);
} }
/** /**
@ -248,67 +248,42 @@ public class CharSequenceUtil extends StrChecker {
* 注意{@link String#trim()}不同此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白 因而可以除去英文字符集之外的其它空白如中文空格 * 注意{@link String#trim()}不同此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白 因而可以除去英文字符集之外的其它空白如中文空格
* *
* <pre> * <pre>
* trimEnd(null) = null * trimSuffix(null) = null
* trimEnd(&quot;&quot;) = &quot;&quot; * trimSuffix(&quot;&quot;) = &quot;&quot;
* trimEnd(&quot;abc&quot;) = &quot;abc&quot; * trimSuffix(&quot;abc&quot;) = &quot;abc&quot;
* trimEnd(&quot; abc&quot;) = &quot; abc&quot; * trimSuffix(&quot; abc&quot;) = &quot; abc&quot;
* trimEnd(&quot;abc &quot;) = &quot;abc&quot; * trimSuffix(&quot;abc &quot;) = &quot;abc&quot;
* trimEnd(&quot; abc &quot;) = &quot; abc&quot; * trimSuffix(&quot; abc &quot;) = &quot; abc&quot;
* </pre> * </pre>
* *
* @param str 要处理的字符串 * @param str 要处理的字符串
* @return 除去空白的字符串如果原字串为{@code null}或结果字符串为{@code ""}则返回 {@code null} * @return 除去空白的字符串如果原字串为{@code null}或结果字符串为{@code ""}则返回 {@code null}
*/ */
public static String trimEnd(final CharSequence str) { public static String trimSuffix(final CharSequence str) {
return trim(str, 1); return StrTrimer.TRIM_SUFFIX_BLANK.apply(str);
} }
/** /**
* 除去字符串头尾部的空白符如果字符串是{@code null}依然返回{@code null} * 除去字符串头尾部的空白符如果字符串是{@code null}依然返回{@code null}
* *
* @param str 要处理的字符串 * @param str 要处理的字符串
* @param mode {@code -1}表示trimStart{@code 0}表示trim全部 {@code 1}表示trimEnd * @param mode 去除模式可选去除头部尾部两边
* @return 除去指定字符后的的字符串如果原字串为{@code null}则返回{@code null} * @return 除去指定字符后的的字符串如果原字串为{@code null}则返回{@code null}
*/ */
public static String trim(final CharSequence str, final int mode) { public static String trim(final CharSequence str, final StrTrimer.TrimMode mode) {
return trim(str, mode, CharUtil::isBlankChar); return new StrTrimer(mode, CharUtil::isBlankChar).apply(str);
} }
/** /**
* 按照断言除去字符串头尾部的断言为真的字符如果字符串是{@code null}依然返回{@code null} * 按照断言除去字符串头尾部的断言为真的字符如果字符串是{@code null}依然返回{@code null}
* *
* @param str 要处理的字符串 * @param str 要处理的字符串
* @param mode {@code -1}表示trimStart{@code 0}表示trim全部 {@code 1}表示trimEnd * @param mode 去除模式可选去除头部尾部两边
* @param predicate 断言是否过掉字符返回{@code true}表述过滤掉{@code false}表示不过滤 * @param predicate 断言是否过掉字符返回{@code true}表述过滤掉{@code false}表示不过滤
* @return 除去指定字符后的的字符串如果原字串为{@code null}则返回{@code null} * @return 除去指定字符后的的字符串如果原字串为{@code null}则返回{@code null}
* @since 5.7.4
*/ */
public static String trim(final CharSequence str, final int mode, final Predicate<Character> predicate) { public static String trim(final CharSequence str, final StrTrimer.TrimMode mode, final Predicate<Character> predicate) {
final String result; return new StrTrimer(mode, predicate).apply(str);
if (str == null) {
result = null;
} else {
final int length = str.length();
int start = 0;
int end = length;// 扫描字符串头部
if (mode <= 0) {
while ((start < end) && (predicate.test(str.charAt(start)))) {
start++;
}
}// 扫描字符串尾部
if (mode >= 0) {
while ((start < end) && (predicate.test(str.charAt(end - 1)))) {
end--;
}
}
if ((start > 0) || (end < length)) {
result = str.toString().substring(start, end);
} else {
result = str.toString();
}
}
return result;
} }
// endregion // endregion

View File

@ -10,17 +10,51 @@ package cn.hutool.core.text;
public class PasswdStrength { public class PasswdStrength {
/** /**
* 密码等级枚举 * 密码强度等级枚举
*/ */
public enum PASSWD_LEVEL { public enum PASSWD_LEVEL {
EASY, MIDIUM, STRONG, VERY_STRONG, EXTREMELY_STRONG /**
* 简单
*/
EASY,
/**
*
*/
MEDIUM,
/**
*
*/
STRONG,
/**
* 很强
*/
VERY_STRONG,
/**
* 非常强
*/
EXTREMELY_STRONG
} }
/** /**
* 字符类型枚举 * 字符类型枚举
*/ */
public enum CHAR_TYPE { public enum CHAR_TYPE {
NUM, SMALL_LETTER, CAPITAL_LETTER, OTHER_CHAR /**
* 数字
*/
NUM,
/**
* 小写字母
*/
SMALL_LETTER,
/**
* 大写字母
*/
CAPITAL_LETTER,
/**
* 特殊字符
*/
OTHER_CHAR
} }
/** /**
@ -215,7 +249,7 @@ public class PasswdStrength {
case 4: case 4:
case 5: case 5:
case 6: case 6:
return PASSWD_LEVEL.MIDIUM; return PASSWD_LEVEL.MEDIUM;
case 7: case 7:
case 8: case 8:
case 9: case 9:

View File

@ -0,0 +1,99 @@
package cn.hutool.core.text;
import cn.hutool.core.util.CharUtil;
import java.io.Serializable;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
/**
* 字符串头尾去除器<br>
* 按照断言除去字符串头尾部的断言为真的字符如果字符串是{@code null}依然返回{@code null}
*
* @author looly
* @since 6.0.0
*/
public class StrTrimer implements UnaryOperator<CharSequence>, Serializable {
private static final long serialVersionUID = 1L;
/**
* 去除两边空白符
*/
public static StrTrimer TRIM_BLANK = new StrTrimer(TrimMode.BOTH, CharUtil::isBlankChar);
/**
* 去除头部空白符
*/
public static StrTrimer TRIM_PREFIX_BLANK = new StrTrimer(TrimMode.PREFIX, CharUtil::isBlankChar);
/**
* 去除尾部空白符
*/
public static StrTrimer TRIM_SUFFIX_BLANK = new StrTrimer(TrimMode.SUFFIX, CharUtil::isBlankChar);
private final TrimMode mode;
private final Predicate<Character> predicate;
/**
* 构造
*
* @param mode 去除模式可选去除头部尾部两边
* @param predicate 断言是否过掉字符返回{@code true}表述过滤掉{@code false}表示不过滤
*/
public StrTrimer(final TrimMode mode, final Predicate<Character> predicate) {
this.mode = mode;
this.predicate = predicate;
}
@Override
public String apply(final CharSequence str) {
if (StrUtil.isEmpty(str)) {
return StrUtil.str(str);
}
final int length = str.length();
int begin = 0;
int end = length;// 扫描字符串头部
if (mode == TrimMode.PREFIX || mode == TrimMode.BOTH) {
// 扫描字符串头部
while ((begin < end) && (predicate.test(str.charAt(begin)))) {
begin++;
}
}
if (mode == TrimMode.SUFFIX || mode == TrimMode.BOTH) {
// 扫描字符串尾部
while ((begin < end) && (predicate.test(str.charAt(end - 1)))) {
end--;
}
}
final String result;
if ((begin > 0) || (end < length)) {
result = str.toString().substring(begin, end);
} else {
result = str.toString();
}
return result;
}
/**
* 去除模式
*
* @author looly
* @since 6.0.0
*/
public enum TrimMode {
/**
* 字符串头部
*/
PREFIX,
/**
* 字符串尾部
*/
SUFFIX,
/**
* 字符串两边
*/
BOTH;
}
}

View File

@ -4,6 +4,7 @@ import cn.hutool.core.collection.iter.ComputeIter;
import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrTrimer;
import cn.hutool.core.text.StrUtil; import cn.hutool.core.text.StrUtil;
import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
@ -347,7 +348,7 @@ public final class CsvParser extends ComputeIter<CsvRow> implements Closeable, S
final char textDelimiter = this.config.textDelimiter; final char textDelimiter = this.config.textDelimiter;
// 忽略多余引号后的换行符 // 忽略多余引号后的换行符
field = StrUtil.trim(field, 1, (c-> c == CharUtil.LF || c == CharUtil.CR)); field = StrUtil.trim(field, StrTrimer.TrimMode.SUFFIX, (c-> c == CharUtil.LF || c == CharUtil.CR));
field = StrUtil.unWrap(field, textDelimiter); field = StrUtil.unWrap(field, textDelimiter);
field = StrUtil.replace(field, "" + textDelimiter + textDelimiter, textDelimiter + ""); field = StrUtil.replace(field, "" + textDelimiter + textDelimiter, textDelimiter + "");