mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
Merge branch 'v5-dev' into factorial_improved
This commit is contained in:
commit
fb04fb0704
36
CHANGELOG.md
36
CHANGELOG.md
@ -3,6 +3,42 @@
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# 5.4.4 (2020-09-23)
|
||||
|
||||
### 新特性
|
||||
* 【core 】 ServiceLoaderUtil改为使用contextClassLoader(pr#183@Gitee)
|
||||
* 【core 】 NetUtil增加getLocalHostName(pr#1103@Github)
|
||||
* 【extra 】 FTP增加stat方法(issue#I1W346@Gitee)
|
||||
* 【core 】 Convert.toNumber支持类似12.2F这种形式字符串转换(issue#I1VYLJ@Gitee)
|
||||
* 【core 】 使用静态变量替换999等(issue#I1W8IB@Gitee)
|
||||
* 【core 】 URLUtil自动trim(issue#I1W803@Gitee)
|
||||
* 【crypto 】 RC4增加ecrypt(pr#1108@Github)
|
||||
* 【core 】 CharUtil and StrUtil增加@(pr#1106@Github)
|
||||
* 【extra 】 优化EMOJ查询逻辑(pr#1112@Github)
|
||||
* 【extra 】 优化CollUtil交并集结果集合设置初始化大小,避免扩容成本(pr#1110@Github)
|
||||
* 【core 】 优化PageUtil彩虹算法(issue#1110@Github)
|
||||
* 【core 】 IoUtil增加readUtf8方法
|
||||
* 【core 】 优化全局邮箱账户初始化逻辑(pr#1114@Github)
|
||||
* 【http 】 SoapClient增加addSOAPHeader方法
|
||||
* 【http 】 完善StrUtil的注释(pr#186@Gitee)
|
||||
* 【aop 】 去除调试日志(issue#1116@Github)
|
||||
* 【core 】 增加'反转义(pr#1121@Github)
|
||||
* 【poi 】 增加SheetReader和XXXRowHandler(issue#I1WHJP@Gitee)
|
||||
* 【dfa 】 增加过滤符号(pr#1122@Github)
|
||||
* 【dfa 】 SensitiveUtil增加setCharFilter方法(pr#1123@Github)
|
||||
* 【all 】 优化常量大小写规范(pr#188@Gitee)
|
||||
* 【core 】 优化NumberUtil中针对BigDecimal的一些处理逻辑(pr#1127@Github)
|
||||
* 【core 】 NumberUtil.factorial注释明确(pr#1126@Github)
|
||||
* 【core 】 NumberUtil增加isPowerOfTwo方法(pr#1132@Github)
|
||||
|
||||
### Bug修复
|
||||
* 【crypto 】 修复SM2验签后无法解密问题(issue#I1W0VP@Gitee)
|
||||
* 【core 】 修复新建默认TreeSet没有默认比较器导致的问题(issue#1101@Github)
|
||||
* 【core 】 修复Linux下使用Windows路径分隔符导致的解压错误(issue#I1MW0E@Gitee)
|
||||
* 【core 】 修复Word07Writer写出map问题(issue#I1W49R@Gitee)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# 5.4.3 (2020-09-16)
|
||||
|
||||
### 新特性
|
||||
|
@ -120,19 +120,19 @@ Each module can be introduced individually, or all modules can be introduced by
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### Gradle
|
||||
```
|
||||
compile 'cn.hutool:hutool-all:5.4.3'
|
||||
compile 'cn.hutool:hutool-all:5.4.4'
|
||||
```
|
||||
|
||||
## Download
|
||||
|
||||
- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.3/)
|
||||
- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.3/)
|
||||
- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.4/)
|
||||
- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.4/)
|
||||
|
||||
> note:
|
||||
> Hutool 5.x supports JDK8+ and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available.
|
||||
|
@ -119,21 +119,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### Gradle
|
||||
```
|
||||
compile 'cn.hutool:hutool-all:5.4.3'
|
||||
compile 'cn.hutool:hutool-all:5.4.4'
|
||||
```
|
||||
|
||||
### 非Maven项目
|
||||
|
||||
点击以下任一链接,下载`hutool-all-X.X.X.jar`即可:
|
||||
|
||||
- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.3/)
|
||||
- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.3/)
|
||||
- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.4/)
|
||||
- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.4/)
|
||||
|
||||
> 注意
|
||||
> Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。
|
||||
|
@ -1 +1 @@
|
||||
5.4.3
|
||||
5.4.4
|
||||
|
@ -1 +1 @@
|
||||
var version = '5.4.3'
|
||||
var version = '5.4.4'
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-all</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-aop</artifactId>
|
||||
|
@ -1,7 +1,6 @@
|
||||
package cn.hutool.aop.interceptor;
|
||||
|
||||
import cn.hutool.aop.aspects.Aspect;
|
||||
import cn.hutool.core.lang.Console;
|
||||
import net.sf.cglib.proxy.MethodInterceptor;
|
||||
import net.sf.cglib.proxy.MethodProxy;
|
||||
|
||||
@ -43,7 +42,6 @@ public class CglibInterceptor implements MethodInterceptor, Serializable {
|
||||
if (aspect.before(target, method, args)) {
|
||||
try {
|
||||
// result = proxy.invokeSuper(obj, args);
|
||||
Console.log(target);
|
||||
result = proxy.invoke(target, args);
|
||||
} catch (InvocationTargetException e) {
|
||||
// 异常回调(只捕获业务代码导致的异常,而非反射导致的异常)
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-bloomFilter</artifactId>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-bom</artifactId>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-cache</artifactId>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-captcha</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-core</artifactId>
|
||||
|
@ -41,9 +41,9 @@ public class BeanPath implements Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 表达式边界符号数组 */
|
||||
private static final char[] expChars = { CharUtil.DOT, CharUtil.BRACKET_START, CharUtil.BRACKET_END };
|
||||
private static final char[] EXP_CHARS = { CharUtil.DOT, CharUtil.BRACKET_START, CharUtil.BRACKET_END };
|
||||
|
||||
private boolean isStartWith$ = false;
|
||||
private boolean isStartWith = false;
|
||||
protected List<String> patternParts;
|
||||
|
||||
/**
|
||||
@ -154,7 +154,7 @@ public class BeanPath implements Serializable{
|
||||
subBean = getFieldValue(subBean, patternPart);
|
||||
if (null == subBean) {
|
||||
// 支持表达式的第一个对象为Bean本身(若用户定义表达式$开头,则不做此操作)
|
||||
if (isFirst && false == this.isStartWith$ && BeanUtil.isMatchName(bean, patternPart, true)) {
|
||||
if (isFirst && false == this.isStartWith && BeanUtil.isMatchName(bean, patternPart, true)) {
|
||||
subBean = bean;
|
||||
isFirst = false;
|
||||
} else {
|
||||
@ -229,11 +229,11 @@ public class BeanPath implements Serializable{
|
||||
c = expression.charAt(i);
|
||||
if (0 == i && '$' == c) {
|
||||
// 忽略开头的$符,表示当前对象
|
||||
isStartWith$ = true;
|
||||
isStartWith = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ArrayUtil.contains(expChars, c)) {
|
||||
if (ArrayUtil.contains(EXP_CHARS, c)) {
|
||||
// 处理边界符号
|
||||
if (CharUtil.BRACKET_END == c) {
|
||||
// 中括号(数字下标)结束
|
||||
|
@ -109,6 +109,7 @@ public class BeanCopier<T> implements Copier<T>, Serializable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.dest;
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,8 @@ public class Base32 {
|
||||
|
||||
private Base32() {}
|
||||
|
||||
private static final String base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
private static final int[] base32Lookup = {//
|
||||
private static final String BASE32_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
private static final int[] BASE32_LOOKUP = {//
|
||||
0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, // '0', '1', '2', '3', '4', '5', '6', '7'
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // '8', '9', ':', ';', '<', '=', '>', '?'
|
||||
0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G'
|
||||
@ -68,7 +68,7 @@ public class Base32 {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
base32.append(base32Chars.charAt(digit));
|
||||
base32.append(BASE32_CHARS.charAt(digit));
|
||||
}
|
||||
|
||||
return base32.toString();
|
||||
@ -120,11 +120,11 @@ public class Base32 {
|
||||
lookup = base32.charAt(i) - '0';
|
||||
|
||||
/* Skip chars outside the lookup table */
|
||||
if (lookup < 0 || lookup >= base32Lookup.length) {
|
||||
if (lookup < 0 || lookup >= BASE32_LOOKUP.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
digit = base32Lookup[lookup];
|
||||
digit = BASE32_LOOKUP[lookup];
|
||||
|
||||
/* If this digit is not in the table, ignore it */
|
||||
if (digit == 0xFF) {
|
||||
|
@ -19,7 +19,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
public class Base62 {
|
||||
|
||||
private static final Charset DEFAULT_CHARSET = CharsetUtil.CHARSET_UTF_8;
|
||||
private static final Base62Codec codec = Base62Codec.createGmp();
|
||||
private static final Base62Codec CODEC = Base62Codec.createGmp();
|
||||
|
||||
// -------------------------------------------------------------------- encode
|
||||
/**
|
||||
@ -50,7 +50,7 @@ public class Base62 {
|
||||
* @return 被加密后的字符串
|
||||
*/
|
||||
public static String encode(byte[] source) {
|
||||
return new String(codec.encode(source));
|
||||
return new String(CODEC.encode(source));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,6 +144,6 @@ public class Base62 {
|
||||
* @return 解码后的bytes
|
||||
*/
|
||||
public static byte[] decode(byte[] base62bytes) {
|
||||
return codec.decode(base62bytes);
|
||||
return CODEC.decode(base62bytes);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ package cn.hutool.core.codec;
|
||||
public class Caesar {
|
||||
|
||||
// 26个字母表
|
||||
public static final String table = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
|
||||
public static final String TABLE = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
|
||||
|
||||
/**
|
||||
* 传入明文,加密得到密文
|
||||
@ -63,8 +63,8 @@ public class Caesar {
|
||||
* @return 加密后的字符
|
||||
*/
|
||||
private static char encodeChar(char c, int offset) {
|
||||
int position = (table.indexOf(c) + offset) % 52;
|
||||
return table.charAt(position);
|
||||
int position = (TABLE.indexOf(c) + offset) % 52;
|
||||
return TABLE.charAt(position);
|
||||
|
||||
}
|
||||
|
||||
@ -75,11 +75,11 @@ public class Caesar {
|
||||
* @return 解密后的字符
|
||||
*/
|
||||
private static char decodeChar(char c, int offset) {
|
||||
int position = (table.indexOf(c) - offset) % 52;
|
||||
int position = (TABLE.indexOf(c) - offset) % 52;
|
||||
if (position < 0) {
|
||||
position += 52;
|
||||
}
|
||||
return table.charAt(position);
|
||||
return TABLE.charAt(position);
|
||||
}
|
||||
// ----------------------------------------------------------------------------------------- Private method end
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ import cn.hutool.core.util.StrUtil;
|
||||
*/
|
||||
public class Morse {
|
||||
|
||||
private static final Map<Integer, String> alphabets = new HashMap<>(); // code point -> morse
|
||||
private static final Map<String, Integer> dictionaries = new HashMap<>(); // morse -> code point
|
||||
private static final Map<Integer, String> ALPHABETS = new HashMap<>(); // code point -> morse
|
||||
private static final Map<String, Integer> DICTIONARIES = new HashMap<>(); // morse -> code point
|
||||
|
||||
/**
|
||||
* 注册莫尔斯电码表
|
||||
@ -27,8 +27,8 @@ public class Morse {
|
||||
* @param dict 二进制
|
||||
*/
|
||||
private static void registerMorse(Character abc, String dict) {
|
||||
alphabets.put(Integer.valueOf(abc), dict);
|
||||
dictionaries.put(dict, Integer.valueOf(abc));
|
||||
ALPHABETS.put(Integer.valueOf(abc), dict);
|
||||
DICTIONARIES.put(dict, Integer.valueOf(abc));
|
||||
}
|
||||
|
||||
static {
|
||||
@ -129,7 +129,7 @@ public class Morse {
|
||||
final int len = text.codePointCount(0, text.length());
|
||||
for (int i = 0; i < len; i++) {
|
||||
int codePoint = text.codePointAt(i);
|
||||
String word = alphabets.get(codePoint);
|
||||
String word = ALPHABETS.get(codePoint);
|
||||
if (word == null) {
|
||||
word = Integer.toBinaryString(codePoint);
|
||||
}
|
||||
@ -161,7 +161,7 @@ public class Morse {
|
||||
continue;
|
||||
}
|
||||
word = word.replace(dit, '0').replace(dah, '1');
|
||||
codePoint = dictionaries.get(word);
|
||||
codePoint = DICTIONARIES.get(word);
|
||||
if (codePoint == null) {
|
||||
codePoint = Integer.valueOf(word, 2);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.hutool.core.collection;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.comparator.CompareUtil;
|
||||
import cn.hutool.core.comparator.PinyinComparator;
|
||||
import cn.hutool.core.comparator.PropertyComparator;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
@ -103,22 +104,22 @@ public class CollUtil {
|
||||
* @return 并集的集合,返回 {@link ArrayList}
|
||||
*/
|
||||
public static <T> Collection<T> union(Collection<T> coll1, Collection<T> coll2) {
|
||||
final ArrayList<T> list = new ArrayList<>();
|
||||
if (isEmpty(coll1)) {
|
||||
list.addAll(coll2);
|
||||
return new ArrayList<>(coll2);
|
||||
} else if (isEmpty(coll2)) {
|
||||
list.addAll(coll1);
|
||||
} else {
|
||||
final Map<T, Integer> map1 = countMap(coll1);
|
||||
final Map<T, Integer> map2 = countMap(coll2);
|
||||
final Set<T> elts = newHashSet(coll2);
|
||||
elts.addAll(coll1);
|
||||
int m;
|
||||
for (T t : elts) {
|
||||
m = Math.max(Convert.toInt(map1.get(t), 0), Convert.toInt(map2.get(t), 0));
|
||||
for (int i = 0; i < m; i++) {
|
||||
list.add(t);
|
||||
}
|
||||
return new ArrayList<>(coll1);
|
||||
}
|
||||
|
||||
final ArrayList<T> list = new ArrayList<>(Math.max(coll1.size(), coll2.size()));
|
||||
final Map<T, Integer> map1 = countMap(coll1);
|
||||
final Map<T, Integer> map2 = countMap(coll2);
|
||||
final Set<T> elts = newHashSet(coll2);
|
||||
elts.addAll(coll1);
|
||||
int m;
|
||||
for (T t : elts) {
|
||||
m = Math.max(Convert.toInt(map1.get(t), 0), Convert.toInt(map2.get(t), 0));
|
||||
for (int i = 0; i < m; i++) {
|
||||
list.add(t);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
@ -225,8 +226,8 @@ public class CollUtil {
|
||||
* @return 交集的集合,返回 {@link ArrayList}
|
||||
*/
|
||||
public static <T> Collection<T> intersection(Collection<T> coll1, Collection<T> coll2) {
|
||||
final ArrayList<T> list = new ArrayList<>();
|
||||
if (isNotEmpty(coll1) && isNotEmpty(coll2)) {
|
||||
final ArrayList<T> list = new ArrayList<>(Math.min(coll1.size(), coll2.size()));
|
||||
final Map<T, Integer> map1 = countMap(coll1);
|
||||
final Map<T, Integer> map2 = countMap(coll2);
|
||||
final Set<T> elts = newHashSet(coll2);
|
||||
@ -237,8 +238,10 @@ public class CollUtil {
|
||||
list.add(t);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
return list;
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -992,8 +995,13 @@ public class CollUtil {
|
||||
} else if (collectionType.isAssignableFrom(LinkedHashSet.class)) {
|
||||
list = new LinkedHashSet<>();
|
||||
} else if (collectionType.isAssignableFrom(TreeSet.class)) {
|
||||
//noinspection SortedCollectionWithNonComparableKeys
|
||||
list = new TreeSet<>();
|
||||
list = new TreeSet<>((o1, o2) -> {
|
||||
// 优先按照对象本身比较,如果没有实现比较接口,默认按照toString内容比较
|
||||
if (o1 instanceof Comparable) {
|
||||
return ((Comparable<T>) o1).compareTo(o2);
|
||||
}
|
||||
return CompareUtil.compare(o1.toString(), o2.toString());
|
||||
});
|
||||
} else if (collectionType.isAssignableFrom(EnumSet.class)) {
|
||||
list = (Collection<T>) EnumSet.noneOf((Class<Enum>) ClassUtil.getTypeArgument(collectionType));
|
||||
}
|
||||
@ -2840,10 +2848,10 @@ public class CollUtil {
|
||||
/**
|
||||
* 使用给定的转换函数,转换源集合为新类型的集合
|
||||
*
|
||||
* @param <F> 源元素类型
|
||||
* @param <T> 目标元素类型
|
||||
* @param <F> 源元素类型
|
||||
* @param <T> 目标元素类型
|
||||
* @param collection 集合
|
||||
* @param function 转换函数
|
||||
* @param function 转换函数
|
||||
* @return 新类型的集合
|
||||
* @since 5.4.3
|
||||
*/
|
||||
|
@ -12,22 +12,22 @@ public enum BasicType {
|
||||
BYTE, SHORT, INT, INTEGER, LONG, DOUBLE, FLOAT, BOOLEAN, CHAR, CHARACTER, STRING;
|
||||
|
||||
/** 包装类型为Key,原始类型为Value,例如: Integer.class =》 int.class. */
|
||||
public static final Map<Class<?>, Class<?>> wrapperPrimitiveMap = new ConcurrentHashMap<>(8);
|
||||
public static final Map<Class<?>, Class<?>> WRAPPER_PRIMITIVE_MAP = new ConcurrentHashMap<>(8);
|
||||
/** 原始类型为Key,包装类型为Value,例如: int.class =》 Integer.class. */
|
||||
public static final Map<Class<?>, Class<?>> primitiveWrapperMap = new ConcurrentHashMap<>(8);
|
||||
public static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_MAP = new ConcurrentHashMap<>(8);
|
||||
|
||||
static {
|
||||
wrapperPrimitiveMap.put(Boolean.class, boolean.class);
|
||||
wrapperPrimitiveMap.put(Byte.class, byte.class);
|
||||
wrapperPrimitiveMap.put(Character.class, char.class);
|
||||
wrapperPrimitiveMap.put(Double.class, double.class);
|
||||
wrapperPrimitiveMap.put(Float.class, float.class);
|
||||
wrapperPrimitiveMap.put(Integer.class, int.class);
|
||||
wrapperPrimitiveMap.put(Long.class, long.class);
|
||||
wrapperPrimitiveMap.put(Short.class, short.class);
|
||||
WRAPPER_PRIMITIVE_MAP.put(Boolean.class, boolean.class);
|
||||
WRAPPER_PRIMITIVE_MAP.put(Byte.class, byte.class);
|
||||
WRAPPER_PRIMITIVE_MAP.put(Character.class, char.class);
|
||||
WRAPPER_PRIMITIVE_MAP.put(Double.class, double.class);
|
||||
WRAPPER_PRIMITIVE_MAP.put(Float.class, float.class);
|
||||
WRAPPER_PRIMITIVE_MAP.put(Integer.class, int.class);
|
||||
WRAPPER_PRIMITIVE_MAP.put(Long.class, long.class);
|
||||
WRAPPER_PRIMITIVE_MAP.put(Short.class, short.class);
|
||||
|
||||
for (Map.Entry<Class<?>, Class<?>> entry : wrapperPrimitiveMap.entrySet()) {
|
||||
primitiveWrapperMap.put(entry.getValue(), entry.getKey());
|
||||
for (Map.Entry<Class<?>, Class<?>> entry : WRAPPER_PRIMITIVE_MAP.entrySet()) {
|
||||
PRIMITIVE_WRAPPER_MAP.put(entry.getValue(), entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ public enum BasicType {
|
||||
if(null == clazz || false == clazz.isPrimitive()){
|
||||
return clazz;
|
||||
}
|
||||
Class<?> result = primitiveWrapperMap.get(clazz);
|
||||
Class<?> result = PRIMITIVE_WRAPPER_MAP.get(clazz);
|
||||
return (null == result) ? clazz : result;
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ public enum BasicType {
|
||||
if(null == clazz || clazz.isPrimitive()){
|
||||
return clazz;
|
||||
}
|
||||
Class<?> result = wrapperPrimitiveMap.get(clazz);
|
||||
Class<?> result = WRAPPER_PRIMITIVE_MAP.get(clazz);
|
||||
return (null == result) ? clazz : result;
|
||||
}
|
||||
}
|
||||
|
@ -106,9 +106,9 @@ public class ConverterRegistry implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得单例的 {@link ConverterRegistry}
|
||||
* 获得单例的 ConverterRegistry
|
||||
*
|
||||
* @return {@link ConverterRegistry}
|
||||
* @return ConverterRegistry
|
||||
*/
|
||||
public static ConverterRegistry getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
@ -140,7 +140,7 @@ public class ConverterRegistry implements Serializable {
|
||||
*
|
||||
* @param type 转换的目标类型
|
||||
* @param converterClass 转换器类,必须有默认构造方法
|
||||
* @return {@link ConverterRegistry}
|
||||
* @return ConverterRegistry
|
||||
*/
|
||||
public ConverterRegistry putCustom(Type type, Class<? extends Converter<?>> converterClass) {
|
||||
return putCustom(type, ReflectUtil.newInstance(converterClass));
|
||||
@ -151,7 +151,7 @@ public class ConverterRegistry implements Serializable {
|
||||
*
|
||||
* @param type 转换的目标类型
|
||||
* @param converter 转换器
|
||||
* @return {@link ConverterRegistry}
|
||||
* @return ConverterRegistry
|
||||
*/
|
||||
public ConverterRegistry putCustom(Type type, Converter<?> converter) {
|
||||
if (null == customConverterMap) {
|
||||
@ -257,6 +257,7 @@ public class ConverterRegistry implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 特殊类型转换,包括Collection、Map、强转、Array等
|
||||
final T result = convertSpecial(type, rowType, value, defaultValue);
|
||||
if (null != result) {
|
||||
@ -269,7 +270,7 @@ public class ConverterRegistry implements Serializable {
|
||||
}
|
||||
|
||||
// 无法转换
|
||||
throw new ConvertException("No Converter for type [{}]", rowType.getName());
|
||||
throw new ConvertException("Can not Converter from [{}] to [{}]", value.getClass().getName(), type.getTypeName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,20 +18,20 @@ public class NumberChineseFormatter {
|
||||
/**
|
||||
* 简体中文形式
|
||||
**/
|
||||
private static final String[] simpleDigits = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
|
||||
private static final String[] SIMPLE_DIGITS = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
|
||||
/**
|
||||
* 繁体中文形式
|
||||
**/
|
||||
private static final String[] traditionalDigits = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
|
||||
private static final String[] TRADITIONAL_DIGITS = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
|
||||
|
||||
/**
|
||||
* 简体中文单位
|
||||
**/
|
||||
private static final String[] simpleUnits = {"", "十", "百", "千"};
|
||||
private static final String[] SIMPLE_UNITS = {"", "十", "百", "千"};
|
||||
/**
|
||||
* 繁体中文单位
|
||||
**/
|
||||
private static final String[] traditionalUnits = {"", "拾", "佰", "仟"};
|
||||
private static final String[] TRADITIONAL_UNITS = {"", "拾", "佰", "仟"};
|
||||
|
||||
/**
|
||||
* 阿拉伯数字转换成中文,小数点后四舍五入保留两位. 使用于整数、小数的转换.
|
||||
@ -53,7 +53,7 @@ public class NumberChineseFormatter {
|
||||
* @return 中文
|
||||
*/
|
||||
public static String format(double amount, boolean isUseTraditional, boolean isMoneyMode) {
|
||||
final String[] numArray = isUseTraditional ? traditionalDigits : simpleDigits;
|
||||
final String[] numArray = isUseTraditional ? TRADITIONAL_DIGITS : SIMPLE_DIGITS;
|
||||
|
||||
if (amount > 99999999999999.99 || amount < -99999999999999.99) {
|
||||
throw new IllegalArgumentException("Number support only: (-99999999999999.99 ~ 99999999999999.99)!");
|
||||
@ -150,7 +150,7 @@ public class NumberChineseFormatter {
|
||||
* @since 5.3.9
|
||||
*/
|
||||
public static String numberCharToChinese(char c, boolean isUseTraditional) {
|
||||
String[] numArray = isUseTraditional ? traditionalDigits : simpleDigits;
|
||||
String[] numArray = isUseTraditional ? TRADITIONAL_DIGITS : SIMPLE_DIGITS;
|
||||
int index = c - 48;
|
||||
if (index < 0 || index >= numArray.length) {
|
||||
return String.valueOf(c);
|
||||
@ -170,8 +170,8 @@ public class NumberChineseFormatter {
|
||||
// throw new IllegalArgumentException("Number must 0 < num < 10000!");
|
||||
// }
|
||||
|
||||
String[] numArray = isUseTraditional ? traditionalDigits : simpleDigits;
|
||||
String[] units = isUseTraditional ? traditionalUnits : simpleUnits;
|
||||
String[] numArray = isUseTraditional ? TRADITIONAL_DIGITS : SIMPLE_DIGITS;
|
||||
String[] units = isUseTraditional ? TRADITIONAL_UNITS : SIMPLE_UNITS;
|
||||
|
||||
int temp = amountPart;
|
||||
|
||||
|
@ -2,6 +2,7 @@ package cn.hutool.core.convert.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Converter;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.TypeUtil;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
@ -60,13 +61,8 @@ public class CollectionConverter implements Converter<Collection<?>> {
|
||||
|
||||
@Override
|
||||
public Collection<?> convert(Object value, Collection<?> defaultValue) throws IllegalArgumentException {
|
||||
Collection<?> result;
|
||||
try {
|
||||
result = convertInternal(value);
|
||||
} catch (RuntimeException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
return ((null == result) ? defaultValue : result);
|
||||
final Collection<?> result = convertInternal(value);
|
||||
return ObjectUtil.defaultIfNull(result, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,7 +207,16 @@ public class NumberConverter extends AbstractConverter<Number> {
|
||||
|
||||
@Override
|
||||
protected String convertToStr(Object value) {
|
||||
return StrUtil.trim(super.convertToStr(value));
|
||||
String result = StrUtil.trim(super.convertToStr(value));
|
||||
if(StrUtil.isNotEmpty(result)){
|
||||
final char c = Character.toUpperCase(result.charAt(result.length() - 1));
|
||||
if(c == 'D' || c == 'L' || c == 'F'){
|
||||
// 类型标识形式(例如123.6D)
|
||||
return StrUtil.subPre(result, -1);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,7 +21,7 @@ public class ChineseDate {
|
||||
/**
|
||||
* 1900-01-31
|
||||
*/
|
||||
private static final long baseDate = -2206425943000L;
|
||||
private static final long BASE_DATE = -2206425943000L;
|
||||
//农历年
|
||||
private final int year;
|
||||
//农历月
|
||||
@ -46,7 +46,7 @@ public class ChineseDate {
|
||||
*/
|
||||
public ChineseDate(Date date) {
|
||||
// 求出和1900年1月31日相差的天数
|
||||
int offset = (int) ((date.getTime() - baseDate) / DateUnit.DAY.getMillis());
|
||||
int offset = (int) ((date.getTime() - BASE_DATE) / DateUnit.DAY.getMillis());
|
||||
// 计算农历年份
|
||||
// 用offset减去每农历年的天数,计算当天是农历第几天,offset是当年的第几天
|
||||
int daysOfYear;
|
||||
@ -299,7 +299,7 @@ public class ChineseDate {
|
||||
if (D >= firstNode) {
|
||||
gzM = GanZhi.cyclicalm((Y - LunarInfo.BASE_YEAR) * 12 + M + 12);
|
||||
}
|
||||
int dayCyclical = (int) ((DateUtil.parseDate(Y + "-" + M + "-" + "1").getTime() - baseDate + 2592000000L) / DateUnit.DAY.getMillis()) + 10;
|
||||
int dayCyclical = (int) ((DateUtil.parseDate(Y + "-" + M + "-" + "1").getTime() - BASE_DATE + 2592000000L) / DateUnit.DAY.getMillis()) + 10;
|
||||
String gzD = GanZhi.cyclicalm(dayCyclical + D - 1);
|
||||
return gzyear + "年" + gzM + "月" + gzD + "日";
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import cn.hutool.core.util.ArrayUtil;
|
||||
public class DateModifier {
|
||||
|
||||
/** 忽略的计算的字段 */
|
||||
private static final int[] ignoreFields = new int[] { //
|
||||
private static final int[] IGNORE_FIELDS = new int[] { //
|
||||
Calendar.HOUR_OF_DAY, // 与HOUR同名
|
||||
Calendar.AM_PM, // 此字段单独处理,不参与计算起始和结束
|
||||
Calendar.DAY_OF_WEEK_IN_MONTH, // 不参与计算
|
||||
@ -62,7 +62,7 @@ public class DateModifier {
|
||||
|
||||
// 循环处理各级字段,精确到毫秒字段
|
||||
for (int i = dateField + 1; i <= Calendar.MILLISECOND; i++) {
|
||||
if (ArrayUtil.contains(ignoreFields, i)) {
|
||||
if (ArrayUtil.contains(IGNORE_FIELDS, i)) {
|
||||
// 忽略无关字段(WEEK_OF_MONTH)始终不做修改
|
||||
continue;
|
||||
}
|
||||
|
@ -21,13 +21,7 @@ import java.time.Year;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
@ -220,9 +214,14 @@ public class DateUtil extends CalendarUtil {
|
||||
|
||||
/**
|
||||
* 获得指定日期是所在年份的第几周<br>
|
||||
* 此方法返回值与一周的第一天有关,比如:<br>
|
||||
* 2016年1月3日为周日,如果一周的第一天为周日,那这天是第二周(返回2)<br>
|
||||
* 如果一周的第一天为周一,那这天是第一周(返回1)<br>
|
||||
* 跨年的那个星期得到的结果总是1
|
||||
*
|
||||
* @param date 日期
|
||||
* @return 周
|
||||
* @see DateTime#setFirstDayOfWeek(Week)
|
||||
*/
|
||||
public static int weekOfYear(Date date) {
|
||||
return DateTime.of(date).weekOfYear();
|
||||
|
@ -428,7 +428,7 @@ public class LocalDateTimeUtil {
|
||||
* @return 一天的开始时间
|
||||
*/
|
||||
public static LocalDateTime beginOfDay(LocalDateTime time) {
|
||||
return time.with(LocalTime.of(0, 0, 0, 0));
|
||||
return time.with(LocalTime.MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -438,7 +438,7 @@ public class LocalDateTimeUtil {
|
||||
* @return 一天的结束时间
|
||||
*/
|
||||
public static LocalDateTime endOfDay(LocalDateTime time) {
|
||||
return time.with(LocalTime.of(23, 59, 59, 999_999_999));
|
||||
return time.with(LocalTime.MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,7 @@ import java.util.Date;
|
||||
public class Zodiac {
|
||||
|
||||
/** 星座分隔时间日 */
|
||||
private static final int[] dayArr = new int[] { 20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22 };
|
||||
private static final int[] DAY_ARR = new int[] { 20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22 };
|
||||
/** 星座 */
|
||||
private static final String[] ZODIACS = new String[] { "摩羯座", "水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "摩羯座" };
|
||||
private static final String[] CHINESE_ZODIACS = new String[] { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };
|
||||
@ -61,7 +61,7 @@ public class Zodiac {
|
||||
*/
|
||||
public static String getZodiac(int month, int day) {
|
||||
// 在分隔日前为前一个星座,否则为后一个星座
|
||||
return day < dayArr[month] ? ZODIACS[month] : ZODIACS[month + 1];
|
||||
return day < DAY_ARR[month] ? ZODIACS[month] : ZODIACS[month + 1];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------- 生肖
|
||||
|
@ -15,71 +15,71 @@ public class LunarFestival {
|
||||
|
||||
//农历节日 *表示放假日
|
||||
// 来自:https://baike.baidu.com/item/%E4%B8%AD%E5%9B%BD%E4%BC%A0%E7%BB%9F%E8%8A%82%E6%97%A5/396100
|
||||
private static final TableMap<Pair<Integer, Integer>, String> lFtv = new TableMap<>(16);
|
||||
private static final TableMap<Pair<Integer, Integer>, String> L_FTV = new TableMap<>(16);
|
||||
static{
|
||||
lFtv.put(new Pair<>(1, 1), "春节");
|
||||
lFtv.put(new Pair<>(1, 2), "犬日");
|
||||
lFtv.put(new Pair<>(1, 3), "猪日");
|
||||
lFtv.put(new Pair<>(1, 4), "羊日");
|
||||
lFtv.put(new Pair<>(1, 5), "牛日 破五日");
|
||||
lFtv.put(new Pair<>(1, 6), "马日 送穷日");
|
||||
lFtv.put(new Pair<>(1, 7), "人日 人胜节");
|
||||
lFtv.put(new Pair<>(1, 8), "谷日 八仙日");
|
||||
lFtv.put(new Pair<>(1, 9), "天日 九皇会");
|
||||
lFtv.put(new Pair<>(1, 10), "地日 石头生日");
|
||||
lFtv.put(new Pair<>(1, 12), "火日 老鼠娶媳妇日");
|
||||
lFtv.put(new Pair<>(1, 13), "上(试)灯日 关公升天日");
|
||||
lFtv.put(new Pair<>(1, 15), "元宵节");
|
||||
lFtv.put(new Pair<>(1, 18), "落灯日");
|
||||
L_FTV.put(new Pair<>(1, 1), "春节");
|
||||
L_FTV.put(new Pair<>(1, 2), "犬日");
|
||||
L_FTV.put(new Pair<>(1, 3), "猪日");
|
||||
L_FTV.put(new Pair<>(1, 4), "羊日");
|
||||
L_FTV.put(new Pair<>(1, 5), "牛日 破五日");
|
||||
L_FTV.put(new Pair<>(1, 6), "马日 送穷日");
|
||||
L_FTV.put(new Pair<>(1, 7), "人日 人胜节");
|
||||
L_FTV.put(new Pair<>(1, 8), "谷日 八仙日");
|
||||
L_FTV.put(new Pair<>(1, 9), "天日 九皇会");
|
||||
L_FTV.put(new Pair<>(1, 10), "地日 石头生日");
|
||||
L_FTV.put(new Pair<>(1, 12), "火日 老鼠娶媳妇日");
|
||||
L_FTV.put(new Pair<>(1, 13), "上(试)灯日 关公升天日");
|
||||
L_FTV.put(new Pair<>(1, 15), "元宵节");
|
||||
L_FTV.put(new Pair<>(1, 18), "落灯日");
|
||||
|
||||
// 二月
|
||||
lFtv.put(new Pair<>(2, 1), "中和节 太阳生日");
|
||||
lFtv.put(new Pair<>(2, 2), "龙抬头");
|
||||
lFtv.put(new Pair<>(2, 12), "花朝节");
|
||||
lFtv.put(new Pair<>(2, 19), "观世音圣诞");
|
||||
L_FTV.put(new Pair<>(2, 1), "中和节 太阳生日");
|
||||
L_FTV.put(new Pair<>(2, 2), "龙抬头");
|
||||
L_FTV.put(new Pair<>(2, 12), "花朝节");
|
||||
L_FTV.put(new Pair<>(2, 19), "观世音圣诞");
|
||||
|
||||
// 三月
|
||||
lFtv.put(new Pair<>(3, 3), "上巳节");
|
||||
L_FTV.put(new Pair<>(3, 3), "上巳节");
|
||||
|
||||
// 四月
|
||||
lFtv.put(new Pair<>(4, 1), "祭雹神");
|
||||
lFtv.put(new Pair<>(4, 4), "文殊菩萨诞辰");
|
||||
lFtv.put(new Pair<>(4, 8), "佛诞节");
|
||||
L_FTV.put(new Pair<>(4, 1), "祭雹神");
|
||||
L_FTV.put(new Pair<>(4, 4), "文殊菩萨诞辰");
|
||||
L_FTV.put(new Pair<>(4, 8), "佛诞节");
|
||||
|
||||
// 五月
|
||||
lFtv.put(new Pair<>(5, 5), "端午节");
|
||||
L_FTV.put(new Pair<>(5, 5), "端午节");
|
||||
|
||||
// 六月
|
||||
lFtv.put(new Pair<>(6, 6), "晒衣节 姑姑节");
|
||||
lFtv.put(new Pair<>(6, 6), "天贶节");
|
||||
lFtv.put(new Pair<>(6, 24), "彝族火把节");
|
||||
L_FTV.put(new Pair<>(6, 6), "晒衣节 姑姑节");
|
||||
L_FTV.put(new Pair<>(6, 6), "天贶节");
|
||||
L_FTV.put(new Pair<>(6, 24), "彝族火把节");
|
||||
|
||||
// 七月
|
||||
lFtv.put(new Pair<>(7, 7), "七夕");
|
||||
lFtv.put(new Pair<>(7, 14), "鬼节(南方)");
|
||||
lFtv.put(new Pair<>(7, 15), "中元节");
|
||||
lFtv.put(new Pair<>(7, 15), "盂兰盆节");
|
||||
lFtv.put(new Pair<>(7, 30), "地藏节");
|
||||
L_FTV.put(new Pair<>(7, 7), "七夕");
|
||||
L_FTV.put(new Pair<>(7, 14), "鬼节(南方)");
|
||||
L_FTV.put(new Pair<>(7, 15), "中元节");
|
||||
L_FTV.put(new Pair<>(7, 15), "盂兰盆节");
|
||||
L_FTV.put(new Pair<>(7, 30), "地藏节");
|
||||
|
||||
// 八月
|
||||
lFtv.put(new Pair<>(8, 15), "中秋节");
|
||||
L_FTV.put(new Pair<>(8, 15), "中秋节");
|
||||
|
||||
// 九月
|
||||
lFtv.put(new Pair<>(9, 9), "重阳节");
|
||||
L_FTV.put(new Pair<>(9, 9), "重阳节");
|
||||
|
||||
// 十月
|
||||
lFtv.put(new Pair<>(10, 1), "祭祖节");
|
||||
lFtv.put(new Pair<>(10, 15), "下元节");
|
||||
L_FTV.put(new Pair<>(10, 1), "祭祖节");
|
||||
L_FTV.put(new Pair<>(10, 15), "下元节");
|
||||
|
||||
// 十一月
|
||||
lFtv.put(new Pair<>(11, 17), "阿弥陀佛圣诞");
|
||||
L_FTV.put(new Pair<>(11, 17), "阿弥陀佛圣诞");
|
||||
|
||||
// 腊月
|
||||
lFtv.put(new Pair<>(12, 8), "腊八节");
|
||||
lFtv.put(new Pair<>(12, 16), "尾牙");
|
||||
lFtv.put(new Pair<>(12, 23), "小年");
|
||||
lFtv.put(new Pair<>(12, 29), "除夕");
|
||||
lFtv.put(new Pair<>(12, 30), "除夕");
|
||||
L_FTV.put(new Pair<>(12, 8), "腊八节");
|
||||
L_FTV.put(new Pair<>(12, 16), "尾牙");
|
||||
L_FTV.put(new Pair<>(12, 23), "小年");
|
||||
L_FTV.put(new Pair<>(12, 29), "除夕");
|
||||
L_FTV.put(new Pair<>(12, 30), "除夕");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,6 +90,6 @@ public class LunarFestival {
|
||||
* @return 获得农历节日
|
||||
*/
|
||||
public static List<String> getFestivals(int month, int day) {
|
||||
return lFtv.getValues(new Pair<>(month, day));
|
||||
return L_FTV.getValues(new Pair<>(month, day));
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ public class SolarTerms {
|
||||
return -1;
|
||||
}
|
||||
|
||||
String _table = sTermInfo[y - 1900];
|
||||
String _table = S_TERM_INFO[y - 1900];
|
||||
Integer[] _info = new Integer[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
_info[i] = NumberUtil.parseInt("0x" + _table.substring(i * 5, 5 * (i + 1)));
|
||||
@ -44,7 +44,7 @@ public class SolarTerms {
|
||||
* 1900-2100各年的24节气日期速查表
|
||||
* 此表来自:https://github.com/jjonline/calendar.js/blob/master/calendar.js
|
||||
*/
|
||||
private static final String[] sTermInfo = new String[]{
|
||||
private static final String[] S_TERM_INFO = new String[]{
|
||||
"9778397bd097c36b0b6fc9274c91aa", "97b6b97bd19801ec9210c965cc920e", "97bcf97c3598082c95f8c965cc920f",
|
||||
"97bd0b06bdb0722c965ce1cfcc920f", "b027097bd097c36b0b6fc9274c91aa", "97b6b97bd19801ec9210c965cc920e",
|
||||
"97bcf97c359801ec95f8c965cc920f", "97bd0b06bdb0722c965ce1cfcc920f", "b027097bd097c36b0b6fc9274c91aa",
|
||||
|
@ -38,7 +38,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
/** SHORT locale dependent date or time style. */
|
||||
public static final int SHORT = DateFormat.SHORT;
|
||||
|
||||
private static final FormatCache<FastDateFormat> cache = new FormatCache<FastDateFormat>(){
|
||||
private static final FormatCache<FastDateFormat> CACHE = new FormatCache<FastDateFormat>(){
|
||||
@Override
|
||||
protected FastDateFormat createInstance(final String pattern, final TimeZone timeZone, final Locale locale) {
|
||||
return new FastDateFormat(pattern, timeZone, locale);
|
||||
@ -55,7 +55,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getInstance() {
|
||||
return cache.getInstance();
|
||||
return CACHE.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,7 +67,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @throws IllegalArgumentException 日期格式问题
|
||||
*/
|
||||
public static FastDateFormat getInstance(final String pattern) {
|
||||
return cache.getInstance(pattern, null, null);
|
||||
return CACHE.getInstance(pattern, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,7 +80,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @throws IllegalArgumentException 日期格式问题
|
||||
*/
|
||||
public static FastDateFormat getInstance(final String pattern, final TimeZone timeZone) {
|
||||
return cache.getInstance(pattern, timeZone, null);
|
||||
return CACHE.getInstance(pattern, timeZone, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,7 +93,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @throws IllegalArgumentException 日期格式问题
|
||||
*/
|
||||
public static FastDateFormat getInstance(final String pattern, final Locale locale) {
|
||||
return cache.getInstance(pattern, null, locale);
|
||||
return CACHE.getInstance(pattern, null, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,7 +107,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @throws IllegalArgumentException 日期格式问题
|
||||
*/
|
||||
public static FastDateFormat getInstance(final String pattern, final TimeZone timeZone, final Locale locale) {
|
||||
return cache.getInstance(pattern, timeZone, locale);
|
||||
return CACHE.getInstance(pattern, timeZone, locale);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -119,7 +119,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return 本地化 {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getDateInstance(final int style) {
|
||||
return cache.getDateInstance(style, null, null);
|
||||
return CACHE.getDateInstance(style, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,7 +131,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return 本地化 {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getDateInstance(final int style, final Locale locale) {
|
||||
return cache.getDateInstance(style, null, locale);
|
||||
return CACHE.getDateInstance(style, null, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,7 +143,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return 本地化 {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getDateInstance(final int style, final TimeZone timeZone) {
|
||||
return cache.getDateInstance(style, timeZone, null);
|
||||
return CACHE.getDateInstance(style, timeZone, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -156,7 +156,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return 本地化 {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getDateInstance(final int style, final TimeZone timeZone, final Locale locale) {
|
||||
return cache.getDateInstance(style, timeZone, locale);
|
||||
return CACHE.getDateInstance(style, timeZone, locale);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -168,7 +168,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return 本地化 {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getTimeInstance(final int style) {
|
||||
return cache.getTimeInstance(style, null, null);
|
||||
return CACHE.getTimeInstance(style, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,7 +180,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return 本地化 {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getTimeInstance(final int style, final Locale locale) {
|
||||
return cache.getTimeInstance(style, null, locale);
|
||||
return CACHE.getTimeInstance(style, null, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -192,7 +192,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return 本地化 {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getTimeInstance(final int style, final TimeZone timeZone) {
|
||||
return cache.getTimeInstance(style, timeZone, null);
|
||||
return CACHE.getTimeInstance(style, timeZone, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -205,7 +205,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return 本地化 {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getTimeInstance(final int style, final TimeZone timeZone, final Locale locale) {
|
||||
return cache.getTimeInstance(style, timeZone, locale);
|
||||
return CACHE.getTimeInstance(style, timeZone, locale);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -218,7 +218,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return 本地化 {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle) {
|
||||
return cache.getDateTimeInstance(dateStyle, timeStyle, null, null);
|
||||
return CACHE.getDateTimeInstance(dateStyle, timeStyle, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -231,7 +231,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return 本地化 {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle, final Locale locale) {
|
||||
return cache.getDateTimeInstance(dateStyle, timeStyle, null, locale);
|
||||
return CACHE.getDateTimeInstance(dateStyle, timeStyle, null, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -258,7 +258,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter {
|
||||
* @return 本地化 {@link FastDateFormat}
|
||||
*/
|
||||
public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle, final TimeZone timeZone, final Locale locale) {
|
||||
return cache.getDateTimeInstance(dateStyle, timeStyle, timeZone, locale);
|
||||
return CACHE.getDateTimeInstance(dateStyle, timeStyle, timeZone, locale);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- Constructor start
|
||||
|
@ -447,7 +447,7 @@ public class FastDateParser extends AbstractDateBasic implements DateParser {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // OK because we are creating an array with no entries
|
||||
private static final ConcurrentMap<Locale, Strategy>[] caches = new ConcurrentMap[Calendar.FIELD_COUNT];
|
||||
private static final ConcurrentMap<Locale, Strategy>[] CACHES = new ConcurrentMap[Calendar.FIELD_COUNT];
|
||||
|
||||
/**
|
||||
* Get a cache of Strategies for a particular field
|
||||
@ -456,11 +456,11 @@ public class FastDateParser extends AbstractDateBasic implements DateParser {
|
||||
* @return a cache of Locale to Strategy
|
||||
*/
|
||||
private static ConcurrentMap<Locale, Strategy> getCache(final int field) {
|
||||
synchronized (caches) {
|
||||
if (caches[field] == null) {
|
||||
caches[field] = new ConcurrentHashMap<>(3);
|
||||
synchronized (CACHES) {
|
||||
if (CACHES[field] == null) {
|
||||
CACHES[field] = new ConcurrentHashMap<>(3);
|
||||
}
|
||||
return caches[field];
|
||||
return CACHES[field];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1052,7 +1052,7 @@ public class FastDatePrinter extends AbstractDateBasic implements DatePrinter {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
private static final ConcurrentMap<TimeZoneDisplayKey, String> cTimeZoneDisplayCache = new ConcurrentHashMap<>(7);
|
||||
private static final ConcurrentMap<TimeZoneDisplayKey, String> C_TIME_ZONE_DISPLAY_CACHE = new ConcurrentHashMap<>(7);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -1067,11 +1067,11 @@ public class FastDatePrinter extends AbstractDateBasic implements DatePrinter {
|
||||
*/
|
||||
static String getTimeZoneDisplay(final TimeZone tz, final boolean daylight, final int style, final Locale locale) {
|
||||
final TimeZoneDisplayKey key = new TimeZoneDisplayKey(tz, daylight, style, locale);
|
||||
String value = cTimeZoneDisplayCache.get(key);
|
||||
String value = C_TIME_ZONE_DISPLAY_CACHE.get(key);
|
||||
if (value == null) {
|
||||
// This is a very slow call, so cache the results.
|
||||
value = tz.getDisplayName(daylight, style, locale);
|
||||
final String prior = cTimeZoneDisplayCache.putIfAbsent(key, value);
|
||||
final String prior = C_TIME_ZONE_DISPLAY_CACHE.putIfAbsent(key, value);
|
||||
if (prior != null) {
|
||||
value = prior;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ abstract class FormatCache<F extends Format> {
|
||||
|
||||
private final ConcurrentMap<Tuple, F> cInstanceCache = new ConcurrentHashMap<>(7);
|
||||
|
||||
private static final ConcurrentMap<Tuple, String> cDateTimeInstanceCache = new ConcurrentHashMap<>(7);
|
||||
private static final ConcurrentMap<Tuple, String> C_DATE_TIME_INSTANCE_CACHE = new ConcurrentHashMap<>(7);
|
||||
|
||||
/**
|
||||
* 使用默认的pattern、timezone和locale获得缓存中的实例
|
||||
@ -163,7 +163,7 @@ abstract class FormatCache<F extends Format> {
|
||||
static String getPatternForStyle(final Integer dateStyle, final Integer timeStyle, final Locale locale) {
|
||||
final Tuple key = new Tuple(dateStyle, timeStyle, locale);
|
||||
|
||||
String pattern = cDateTimeInstanceCache.get(key);
|
||||
String pattern = C_DATE_TIME_INSTANCE_CACHE.get(key);
|
||||
if (pattern == null) {
|
||||
try {
|
||||
DateFormat formatter;
|
||||
@ -175,7 +175,7 @@ abstract class FormatCache<F extends Format> {
|
||||
formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
|
||||
}
|
||||
pattern = ((SimpleDateFormat) formatter).toPattern();
|
||||
final String previous = cDateTimeInstanceCache.putIfAbsent(key, pattern);
|
||||
final String previous = C_DATE_TIME_INSTANCE_CACHE.putIfAbsent(key, pattern);
|
||||
if (previous != null) {
|
||||
// even though it doesn't matter if another thread put the pattern
|
||||
// it's still good practice to return the String instance that is
|
||||
|
@ -95,7 +95,7 @@ public class GifDecoder {
|
||||
protected int delay = 0; // delay in milliseconds
|
||||
protected int transIndex; // transparent color index
|
||||
|
||||
protected static final int MaxStackSize = 4096;
|
||||
protected static final int MAX_STACK_SIZE = 4096;
|
||||
// max decoder pixel stack size
|
||||
|
||||
// LZW decoder working arrays
|
||||
@ -378,9 +378,9 @@ public class GifDecoder {
|
||||
if ((pixels == null) || (pixels.length < npix)) {
|
||||
pixels = new byte[npix]; // allocate new pixel array
|
||||
}
|
||||
if (prefix == null) prefix = new short[MaxStackSize];
|
||||
if (suffix == null) suffix = new byte[MaxStackSize];
|
||||
if (pixelStack == null) pixelStack = new byte[MaxStackSize + 1];
|
||||
if (prefix == null) prefix = new short[MAX_STACK_SIZE];
|
||||
if (suffix == null) suffix = new byte[MAX_STACK_SIZE];
|
||||
if (pixelStack == null) pixelStack = new byte[MAX_STACK_SIZE + 1];
|
||||
|
||||
// Initialize GIF data stream decoder.
|
||||
|
||||
@ -455,7 +455,7 @@ public class GifDecoder {
|
||||
|
||||
// Add a new string to the string table,
|
||||
|
||||
if (available >= MaxStackSize) {
|
||||
if (available >= MAX_STACK_SIZE) {
|
||||
pixelStack[top++] = (byte) first;
|
||||
continue;
|
||||
}
|
||||
@ -464,7 +464,7 @@ public class GifDecoder {
|
||||
suffix[available] = (byte) first;
|
||||
available++;
|
||||
if (((available & code_mask) == 0)
|
||||
&& (available < MaxStackSize)) {
|
||||
&& (available < MAX_STACK_SIZE)) {
|
||||
code_size++;
|
||||
code_mask += available;
|
||||
}
|
||||
@ -606,10 +606,11 @@ public class GifDecoder {
|
||||
for (int i = 0; i < 11; i++) {
|
||||
app.append((char) block[i]);
|
||||
}
|
||||
if (app.toString().equals("NETSCAPE2.0")) {
|
||||
if ("NETSCAPE2.0".equals(app.toString())) {
|
||||
readNetscapeExt();
|
||||
} else
|
||||
} else {
|
||||
skip(); // don't care
|
||||
}
|
||||
break;
|
||||
|
||||
default: // uninteresting extension
|
||||
|
@ -29,16 +29,16 @@ package cn.hutool.core.img.gif;
|
||||
*/
|
||||
public class NeuQuant {
|
||||
|
||||
protected static final int netsize = 256; /* number of colours used */
|
||||
protected static final int NETSIZE = 256; /* number of colours used */
|
||||
|
||||
/* four primes near 500 - assume no image has a length so large */
|
||||
/* that it is divisible by all four primes */
|
||||
protected static final int prime1 = 499;
|
||||
protected static final int prime2 = 491;
|
||||
protected static final int prime3 = 487;
|
||||
protected static final int prime4 = 503;
|
||||
protected static final int PRIME1 = 499;
|
||||
protected static final int PRIME2 = 491;
|
||||
protected static final int PRIME3 = 487;
|
||||
protected static final int PRIME4 = 503;
|
||||
|
||||
protected static final int minpicturebytes = (3 * prime4);
|
||||
protected static final int MINPICTUREBYTES = (3 * PRIME4);
|
||||
/* minimum size for input image */
|
||||
|
||||
/* Program Skeleton
|
||||
@ -56,38 +56,38 @@ public class NeuQuant {
|
||||
/* Network Definitions
|
||||
------------------- */
|
||||
|
||||
protected static final int maxnetpos = (netsize - 1);
|
||||
protected static final int netbiasshift = 4; /* bias for colour values */
|
||||
protected static final int ncycles = 100; /* no. of learning cycles */
|
||||
protected static final int MAXNETPOS = (NETSIZE - 1);
|
||||
protected static final int NETBIASSHIFT = 4; /* bias for colour values */
|
||||
protected static final int NCYCLES = 100; /* no. of learning cycles */
|
||||
|
||||
/* defs for freq and bias */
|
||||
protected static final int intbiasshift = 16; /* bias for fractions */
|
||||
protected static final int intbias = (1 << intbiasshift);
|
||||
protected static final int gammashift = 10; /* gamma = 1024 */
|
||||
protected static final int gamma = (1 << gammashift);
|
||||
protected static final int betashift = 10;
|
||||
protected static final int beta = (intbias >> betashift); /* beta = 1/1024 */
|
||||
protected static final int betagamma =
|
||||
(intbias << (gammashift - betashift));
|
||||
protected static final int INTBIASSHIFT = 16; /* bias for fractions */
|
||||
protected static final int INTBIAS = (1 << INTBIASSHIFT);
|
||||
protected static final int GAMMASHIFT = 10; /* gamma = 1024 */
|
||||
protected static final int GAMMA = (1 << GAMMASHIFT);
|
||||
protected static final int BETASHIFT = 10;
|
||||
protected static final int BETA = (INTBIAS >> BETASHIFT); /* beta = 1/1024 */
|
||||
protected static final int BETAGAMMA =
|
||||
(INTBIAS << (GAMMASHIFT - BETASHIFT));
|
||||
|
||||
/* defs for decreasing radius factor */
|
||||
protected static final int initrad = (netsize >> 3); /* for 256 cols, radius starts */
|
||||
protected static final int radiusbiasshift = 6; /* at 32.0 biased by 6 bits */
|
||||
protected static final int radiusbias = (1 << radiusbiasshift);
|
||||
protected static final int initradius = (initrad * radiusbias); /* and decreases by a */
|
||||
protected static final int radiusdec = 30; /* factor of 1/30 each cycle */
|
||||
protected static final int INITRAD = (NETSIZE >> 3); /* for 256 cols, radius starts */
|
||||
protected static final int RADIUSBIASSHIFT = 6; /* at 32.0 biased by 6 bits */
|
||||
protected static final int RADIUSBIAS = (1 << RADIUSBIASSHIFT);
|
||||
protected static final int INITRADIUS = (INITRAD * RADIUSBIAS); /* and decreases by a */
|
||||
protected static final int RADIUSDEC = 30; /* factor of 1/30 each cycle */
|
||||
|
||||
/* defs for decreasing alpha factor */
|
||||
protected static final int alphabiasshift = 10; /* alpha starts at 1.0 */
|
||||
protected static final int initalpha = (1 << alphabiasshift);
|
||||
protected static final int ALPHABIASSHIFT = 10; /* alpha starts at 1.0 */
|
||||
protected static final int INITALPHA = (1 << ALPHABIASSHIFT);
|
||||
|
||||
protected int alphadec; /* biased by 10 bits */
|
||||
|
||||
/* radbias and alpharadbias used for radpower calculation */
|
||||
protected static final int radbiasshift = 8;
|
||||
protected static final int radbias = (1 << radbiasshift);
|
||||
protected static final int alpharadbshift = (alphabiasshift + radbiasshift);
|
||||
protected static final int alpharadbias = (1 << alpharadbshift);
|
||||
protected static final int RADBIASSHIFT = 8;
|
||||
protected static final int RADBIAS = (1 << RADBIASSHIFT);
|
||||
protected static final int ALPHARADBSHIFT = (ALPHABIASSHIFT + RADBIASSHIFT);
|
||||
protected static final int ALPHARADBIAS = (1 << ALPHARADBSHIFT);
|
||||
|
||||
/* Types and Global Variables
|
||||
-------------------------- */
|
||||
@ -103,10 +103,10 @@ public class NeuQuant {
|
||||
protected int[] netindex = new int[256];
|
||||
/* for network lookup - really 256 */
|
||||
|
||||
protected int[] bias = new int[netsize];
|
||||
protected int[] bias = new int[NETSIZE];
|
||||
/* bias and freq arrays for learning */
|
||||
protected int[] freq = new int[netsize];
|
||||
protected int[] radpower = new int[initrad];
|
||||
protected int[] freq = new int[NETSIZE];
|
||||
protected int[] radpower = new int[INITRAD];
|
||||
/* radpower for precomputation */
|
||||
|
||||
/* Initialise network in range (0,0,0) to (255,255,255) and set parameters
|
||||
@ -120,23 +120,23 @@ public class NeuQuant {
|
||||
lengthcount = len;
|
||||
samplefac = sample;
|
||||
|
||||
network = new int[netsize][];
|
||||
for (i = 0; i < netsize; i++) {
|
||||
network = new int[NETSIZE][];
|
||||
for (i = 0; i < NETSIZE; i++) {
|
||||
network[i] = new int[4];
|
||||
p = network[i];
|
||||
p[0] = p[1] = p[2] = (i << (netbiasshift + 8)) / netsize;
|
||||
freq[i] = intbias / netsize; /* 1/netsize */
|
||||
p[0] = p[1] = p[2] = (i << (NETBIASSHIFT + 8)) / NETSIZE;
|
||||
freq[i] = INTBIAS / NETSIZE; /* 1/netsize */
|
||||
bias[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] colorMap() {
|
||||
byte[] map = new byte[3 * netsize];
|
||||
int[] index = new int[netsize];
|
||||
for (int i = 0; i < netsize; i++)
|
||||
byte[] map = new byte[3 * NETSIZE];
|
||||
int[] index = new int[NETSIZE];
|
||||
for (int i = 0; i < NETSIZE; i++)
|
||||
index[network[i][3]] = i;
|
||||
int k = 0;
|
||||
for (int i = 0; i < netsize; i++) {
|
||||
for (int i = 0; i < NETSIZE; i++) {
|
||||
int j = index[i];
|
||||
map[k++] = (byte) (network[j][0]);
|
||||
map[k++] = (byte) (network[j][1]);
|
||||
@ -156,12 +156,12 @@ public class NeuQuant {
|
||||
|
||||
previouscol = 0;
|
||||
startpos = 0;
|
||||
for (i = 0; i < netsize; i++) {
|
||||
for (i = 0; i < NETSIZE; i++) {
|
||||
p = network[i];
|
||||
smallpos = i;
|
||||
smallval = p[1]; /* index on g */
|
||||
/* find smallest in i..netsize-1 */
|
||||
for (j = i + 1; j < netsize; j++) {
|
||||
for (j = i + 1; j < NETSIZE; j++) {
|
||||
q = network[j];
|
||||
if (q[1] < smallval) { /* index on g */
|
||||
smallpos = j;
|
||||
@ -193,9 +193,9 @@ public class NeuQuant {
|
||||
startpos = i;
|
||||
}
|
||||
}
|
||||
netindex[previouscol] = (startpos + maxnetpos) >> 1;
|
||||
netindex[previouscol] = (startpos + MAXNETPOS) >> 1;
|
||||
for (j = previouscol + 1; j < 256; j++)
|
||||
netindex[j] = maxnetpos; /* really 256 */
|
||||
netindex[j] = MAXNETPOS; /* really 256 */
|
||||
}
|
||||
|
||||
/* Main Learning Loop
|
||||
@ -207,44 +207,44 @@ public class NeuQuant {
|
||||
byte[] p;
|
||||
int pix, lim;
|
||||
|
||||
if (lengthcount < minpicturebytes)
|
||||
if (lengthcount < MINPICTUREBYTES)
|
||||
samplefac = 1;
|
||||
alphadec = 30 + ((samplefac - 1) / 3);
|
||||
p = thepicture;
|
||||
pix = 0;
|
||||
lim = lengthcount;
|
||||
samplepixels = lengthcount / (3 * samplefac);
|
||||
delta = samplepixels / ncycles;
|
||||
alpha = initalpha;
|
||||
radius = initradius;
|
||||
delta = samplepixels / NCYCLES;
|
||||
alpha = INITALPHA;
|
||||
radius = INITRADIUS;
|
||||
|
||||
rad = radius >> radiusbiasshift;
|
||||
rad = radius >> RADIUSBIASSHIFT;
|
||||
for (i = 0; i < rad; i++)
|
||||
radpower[i] =
|
||||
alpha * (((rad * rad - i * i) * radbias) / (rad * rad));
|
||||
alpha * (((rad * rad - i * i) * RADBIAS) / (rad * rad));
|
||||
|
||||
//fprintf(stderr,"beginning 1D learning: initial radius=%d\n", rad);
|
||||
|
||||
if (lengthcount < minpicturebytes)
|
||||
if (lengthcount < MINPICTUREBYTES)
|
||||
step = 3;
|
||||
else if ((lengthcount % prime1) != 0)
|
||||
step = 3 * prime1;
|
||||
else if ((lengthcount % PRIME1) != 0)
|
||||
step = 3 * PRIME1;
|
||||
else {
|
||||
if ((lengthcount % prime2) != 0)
|
||||
step = 3 * prime2;
|
||||
if ((lengthcount % PRIME2) != 0)
|
||||
step = 3 * PRIME2;
|
||||
else {
|
||||
if ((lengthcount % prime3) != 0)
|
||||
step = 3 * prime3;
|
||||
if ((lengthcount % PRIME3) != 0)
|
||||
step = 3 * PRIME3;
|
||||
else
|
||||
step = 3 * prime4;
|
||||
step = 3 * PRIME4;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < samplepixels) {
|
||||
b = (p[pix] & 0xff) << netbiasshift;
|
||||
g = (p[pix + 1] & 0xff) << netbiasshift;
|
||||
r = (p[pix + 2] & 0xff) << netbiasshift;
|
||||
b = (p[pix] & 0xff) << NETBIASSHIFT;
|
||||
g = (p[pix + 1] & 0xff) << NETBIASSHIFT;
|
||||
r = (p[pix + 2] & 0xff) << NETBIASSHIFT;
|
||||
j = contest(b, g, r);
|
||||
|
||||
altersingle(alpha, j, b, g, r);
|
||||
@ -260,13 +260,13 @@ public class NeuQuant {
|
||||
delta = 1;
|
||||
if (i % delta == 0) {
|
||||
alpha -= alpha / alphadec;
|
||||
radius -= radius / radiusdec;
|
||||
rad = radius >> radiusbiasshift;
|
||||
radius -= radius / RADIUSDEC;
|
||||
rad = radius >> RADIUSBIASSHIFT;
|
||||
if (rad <= 1)
|
||||
rad = 0;
|
||||
for (j = 0; j < rad; j++)
|
||||
radpower[j] =
|
||||
alpha * (((rad * rad - j * j) * radbias) / (rad * rad));
|
||||
alpha * (((rad * rad - j * j) * RADBIAS) / (rad * rad));
|
||||
}
|
||||
}
|
||||
//fprintf(stderr,"finished 1D learning: final alpha=%f !\n",((float)alpha)/initalpha);
|
||||
@ -285,12 +285,12 @@ public class NeuQuant {
|
||||
i = netindex[g]; /* index on g */
|
||||
j = i - 1; /* start at netindex[g] and work outwards */
|
||||
|
||||
while ((i < netsize) || (j >= 0)) {
|
||||
if (i < netsize) {
|
||||
while ((i < NETSIZE) || (j >= 0)) {
|
||||
if (i < NETSIZE) {
|
||||
p = network[i];
|
||||
dist = p[1] - g; /* inx key */
|
||||
if (dist >= bestd)
|
||||
i = netsize; /* stop iter */
|
||||
i = NETSIZE; /* stop iter */
|
||||
else {
|
||||
i++;
|
||||
if (dist < 0)
|
||||
@ -353,10 +353,10 @@ public class NeuQuant {
|
||||
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < netsize; i++) {
|
||||
network[i][0] >>= netbiasshift;
|
||||
network[i][1] >>= netbiasshift;
|
||||
network[i][2] >>= netbiasshift;
|
||||
for (i = 0; i < NETSIZE; i++) {
|
||||
network[i][0] >>= NETBIASSHIFT;
|
||||
network[i][1] >>= NETBIASSHIFT;
|
||||
network[i][2] >>= NETBIASSHIFT;
|
||||
network[i][3] = i; /* record colour no */
|
||||
}
|
||||
}
|
||||
@ -372,8 +372,8 @@ public class NeuQuant {
|
||||
if (lo < -1)
|
||||
lo = -1;
|
||||
hi = i + rad;
|
||||
if (hi > netsize)
|
||||
hi = netsize;
|
||||
if (hi > NETSIZE)
|
||||
hi = NETSIZE;
|
||||
|
||||
j = i + 1;
|
||||
k = i - 1;
|
||||
@ -383,18 +383,18 @@ public class NeuQuant {
|
||||
if (j < hi) {
|
||||
p = network[j++];
|
||||
try {
|
||||
p[0] -= (a * (p[0] - b)) / alpharadbias;
|
||||
p[1] -= (a * (p[1] - g)) / alpharadbias;
|
||||
p[2] -= (a * (p[2] - r)) / alpharadbias;
|
||||
p[0] -= (a * (p[0] - b)) / ALPHARADBIAS;
|
||||
p[1] -= (a * (p[1] - g)) / ALPHARADBIAS;
|
||||
p[2] -= (a * (p[2] - r)) / ALPHARADBIAS;
|
||||
} catch (Exception ignored) {
|
||||
} // prevents 1.3 miscompilation
|
||||
}
|
||||
if (k > lo) {
|
||||
p = network[k--];
|
||||
try {
|
||||
p[0] -= (a * (p[0] - b)) / alpharadbias;
|
||||
p[1] -= (a * (p[1] - g)) / alpharadbias;
|
||||
p[2] -= (a * (p[2] - r)) / alpharadbias;
|
||||
p[0] -= (a * (p[0] - b)) / ALPHARADBIAS;
|
||||
p[1] -= (a * (p[1] - g)) / ALPHARADBIAS;
|
||||
p[2] -= (a * (p[2] - r)) / ALPHARADBIAS;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
@ -407,9 +407,9 @@ public class NeuQuant {
|
||||
|
||||
/* alter hit neuron */
|
||||
int[] n = network[i];
|
||||
n[0] -= (alpha * (n[0] - b)) / initalpha;
|
||||
n[1] -= (alpha * (n[1] - g)) / initalpha;
|
||||
n[2] -= (alpha * (n[2] - r)) / initalpha;
|
||||
n[0] -= (alpha * (n[0] - b)) / INITALPHA;
|
||||
n[1] -= (alpha * (n[1] - g)) / INITALPHA;
|
||||
n[2] -= (alpha * (n[2] - r)) / INITALPHA;
|
||||
}
|
||||
|
||||
/* Search for biased BGR values
|
||||
@ -430,7 +430,7 @@ public class NeuQuant {
|
||||
bestpos = -1;
|
||||
bestbiaspos = bestpos;
|
||||
|
||||
for (i = 0; i < netsize; i++) {
|
||||
for (i = 0; i < NETSIZE; i++) {
|
||||
n = network[i];
|
||||
dist = n[0] - b;
|
||||
if (dist < 0)
|
||||
@ -447,17 +447,17 @@ public class NeuQuant {
|
||||
bestd = dist;
|
||||
bestpos = i;
|
||||
}
|
||||
biasdist = dist - ((bias[i]) >> (intbiasshift - netbiasshift));
|
||||
biasdist = dist - ((bias[i]) >> (INTBIASSHIFT - NETBIASSHIFT));
|
||||
if (biasdist < bestbiasd) {
|
||||
bestbiasd = biasdist;
|
||||
bestbiaspos = i;
|
||||
}
|
||||
betafreq = (freq[i] >> betashift);
|
||||
betafreq = (freq[i] >> BETASHIFT);
|
||||
freq[i] -= betafreq;
|
||||
bias[i] += (betafreq << gammashift);
|
||||
bias[i] += (betafreq << GAMMASHIFT);
|
||||
}
|
||||
freq[bestpos] += beta;
|
||||
bias[bestpos] -= betagamma;
|
||||
freq[bestpos] += BETA;
|
||||
bias[bestpos] -= BETAGAMMA;
|
||||
return (bestbiaspos);
|
||||
}
|
||||
}
|
||||
|
@ -20,60 +20,60 @@ import cn.hutool.core.util.StrUtil;
|
||||
*/
|
||||
public class FileTypeUtil {
|
||||
|
||||
private static final Map<String, String> fileTypeMap;
|
||||
private static final Map<String, String> FILE_TYPE_MAP;
|
||||
|
||||
static {
|
||||
fileTypeMap = new ConcurrentHashMap<>();
|
||||
FILE_TYPE_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
fileTypeMap.put("ffd8ff", "jpg"); // JPEG (jpg)
|
||||
fileTypeMap.put("89504e47", "png"); // PNG (png)
|
||||
fileTypeMap.put("4749463837", "gif"); // GIF (gif)
|
||||
fileTypeMap.put("4749463839", "gif"); // GIF (gif)
|
||||
fileTypeMap.put("49492a00227105008037", "tif"); // TIFF (tif)
|
||||
fileTypeMap.put("424d228c010000000000", "bmp"); // 16色位图(bmp)
|
||||
fileTypeMap.put("424d8240090000000000", "bmp"); // 24位位图(bmp)
|
||||
fileTypeMap.put("424d8e1b030000000000", "bmp"); // 256色位图(bmp)
|
||||
fileTypeMap.put("41433130313500000000", "dwg"); // CAD (dwg)
|
||||
fileTypeMap.put("7b5c727466315c616e73", "rtf"); // Rich Text Format (rtf)
|
||||
fileTypeMap.put("38425053000100000000", "psd"); // Photoshop (psd)
|
||||
fileTypeMap.put("46726f6d3a203d3f6762", "eml"); // Email [Outlook Express 6] (eml)
|
||||
fileTypeMap.put("5374616E64617264204A", "mdb"); // MS Access (mdb)
|
||||
fileTypeMap.put("252150532D41646F6265", "ps");
|
||||
fileTypeMap.put("255044462d312e", "pdf"); // Adobe Acrobat (pdf)
|
||||
fileTypeMap.put("2e524d46000000120001", "rmvb"); // rmvb/rm相同
|
||||
fileTypeMap.put("464c5601050000000900", "flv"); // flv与f4v相同
|
||||
fileTypeMap.put("00000020667479706", "mp4");
|
||||
fileTypeMap.put("00000018667479706D70", "mp4");
|
||||
fileTypeMap.put("49443303000000002176", "mp3");
|
||||
fileTypeMap.put("000001ba210001000180", "mpg"); //
|
||||
fileTypeMap.put("3026b2758e66cf11a6d9", "wmv"); // wmv与asf相同
|
||||
fileTypeMap.put("52494646e27807005741", "wav"); // Wave (wav)
|
||||
fileTypeMap.put("52494646d07d60074156", "avi");
|
||||
fileTypeMap.put("4d546864000000060001", "mid"); // MIDI (mid)
|
||||
fileTypeMap.put("526172211a0700cf9073", "rar");// WinRAR
|
||||
fileTypeMap.put("235468697320636f6e66", "ini");
|
||||
fileTypeMap.put("504B03040a0000000000", "jar");
|
||||
fileTypeMap.put("504B0304140008000800", "jar");
|
||||
FILE_TYPE_MAP.put("ffd8ff", "jpg"); // JPEG (jpg)
|
||||
FILE_TYPE_MAP.put("89504e47", "png"); // PNG (png)
|
||||
FILE_TYPE_MAP.put("4749463837", "gif"); // GIF (gif)
|
||||
FILE_TYPE_MAP.put("4749463839", "gif"); // GIF (gif)
|
||||
FILE_TYPE_MAP.put("49492a00227105008037", "tif"); // TIFF (tif)
|
||||
FILE_TYPE_MAP.put("424d228c010000000000", "bmp"); // 16色位图(bmp)
|
||||
FILE_TYPE_MAP.put("424d8240090000000000", "bmp"); // 24位位图(bmp)
|
||||
FILE_TYPE_MAP.put("424d8e1b030000000000", "bmp"); // 256色位图(bmp)
|
||||
FILE_TYPE_MAP.put("41433130313500000000", "dwg"); // CAD (dwg)
|
||||
FILE_TYPE_MAP.put("7b5c727466315c616e73", "rtf"); // Rich Text Format (rtf)
|
||||
FILE_TYPE_MAP.put("38425053000100000000", "psd"); // Photoshop (psd)
|
||||
FILE_TYPE_MAP.put("46726f6d3a203d3f6762", "eml"); // Email [Outlook Express 6] (eml)
|
||||
FILE_TYPE_MAP.put("5374616E64617264204A", "mdb"); // MS Access (mdb)
|
||||
FILE_TYPE_MAP.put("252150532D41646F6265", "ps");
|
||||
FILE_TYPE_MAP.put("255044462d312e", "pdf"); // Adobe Acrobat (pdf)
|
||||
FILE_TYPE_MAP.put("2e524d46000000120001", "rmvb"); // rmvb/rm相同
|
||||
FILE_TYPE_MAP.put("464c5601050000000900", "flv"); // flv与f4v相同
|
||||
FILE_TYPE_MAP.put("00000020667479706", "mp4");
|
||||
FILE_TYPE_MAP.put("00000018667479706D70", "mp4");
|
||||
FILE_TYPE_MAP.put("49443303000000002176", "mp3");
|
||||
FILE_TYPE_MAP.put("000001ba210001000180", "mpg"); //
|
||||
FILE_TYPE_MAP.put("3026b2758e66cf11a6d9", "wmv"); // wmv与asf相同
|
||||
FILE_TYPE_MAP.put("52494646e27807005741", "wav"); // Wave (wav)
|
||||
FILE_TYPE_MAP.put("52494646d07d60074156", "avi");
|
||||
FILE_TYPE_MAP.put("4d546864000000060001", "mid"); // MIDI (mid)
|
||||
FILE_TYPE_MAP.put("526172211a0700cf9073", "rar");// WinRAR
|
||||
FILE_TYPE_MAP.put("235468697320636f6e66", "ini");
|
||||
FILE_TYPE_MAP.put("504B03040a0000000000", "jar");
|
||||
FILE_TYPE_MAP.put("504B0304140008000800", "jar");
|
||||
// MS Excel 注意:word、msi 和 excel的文件头一样
|
||||
fileTypeMap.put("d0cf11e0a1b11ae10", "xls");
|
||||
fileTypeMap.put("504B0304", "zip");
|
||||
fileTypeMap.put("4d5a9000030000000400", "exe");// 可执行文件
|
||||
fileTypeMap.put("3c25402070616765206c", "jsp");// jsp文件
|
||||
fileTypeMap.put("4d616e69666573742d56", "mf");// MF文件
|
||||
fileTypeMap.put("7061636b616765207765", "java");// java文件
|
||||
fileTypeMap.put("406563686f206f66660d", "bat");// bat文件
|
||||
fileTypeMap.put("1f8b0800000000000000", "gz");// gz文件
|
||||
fileTypeMap.put("cafebabe0000002e0041", "class");// bat文件
|
||||
fileTypeMap.put("49545346030000006000", "chm");// bat文件
|
||||
fileTypeMap.put("04000000010000001300", "mxp");// bat文件
|
||||
fileTypeMap.put("6431303a637265617465", "torrent");
|
||||
fileTypeMap.put("6D6F6F76", "mov"); // Quicktime (mov)
|
||||
fileTypeMap.put("FF575043", "wpd"); // WordPerfect (wpd)
|
||||
fileTypeMap.put("CFAD12FEC5FD746F", "dbx"); // Outlook Express (dbx)
|
||||
fileTypeMap.put("2142444E", "pst"); // Outlook (pst)
|
||||
fileTypeMap.put("AC9EBD8F", "qdf"); // Quicken (qdf)
|
||||
fileTypeMap.put("E3828596", "pwl"); // Windows Password (pwl)
|
||||
fileTypeMap.put("2E7261FD", "ram"); // Real Audio (ram)
|
||||
FILE_TYPE_MAP.put("d0cf11e0a1b11ae10", "xls");
|
||||
FILE_TYPE_MAP.put("504B0304", "zip");
|
||||
FILE_TYPE_MAP.put("4d5a9000030000000400", "exe");// 可执行文件
|
||||
FILE_TYPE_MAP.put("3c25402070616765206c", "jsp");// jsp文件
|
||||
FILE_TYPE_MAP.put("4d616e69666573742d56", "mf");// MF文件
|
||||
FILE_TYPE_MAP.put("7061636b616765207765", "java");// java文件
|
||||
FILE_TYPE_MAP.put("406563686f206f66660d", "bat");// bat文件
|
||||
FILE_TYPE_MAP.put("1f8b0800000000000000", "gz");// gz文件
|
||||
FILE_TYPE_MAP.put("cafebabe0000002e0041", "class");// bat文件
|
||||
FILE_TYPE_MAP.put("49545346030000006000", "chm");// bat文件
|
||||
FILE_TYPE_MAP.put("04000000010000001300", "mxp");// bat文件
|
||||
FILE_TYPE_MAP.put("6431303a637265617465", "torrent");
|
||||
FILE_TYPE_MAP.put("6D6F6F76", "mov"); // Quicktime (mov)
|
||||
FILE_TYPE_MAP.put("FF575043", "wpd"); // WordPerfect (wpd)
|
||||
FILE_TYPE_MAP.put("CFAD12FEC5FD746F", "dbx"); // Outlook Express (dbx)
|
||||
FILE_TYPE_MAP.put("2142444E", "pst"); // Outlook (pst)
|
||||
FILE_TYPE_MAP.put("AC9EBD8F", "qdf"); // Quicken (qdf)
|
||||
FILE_TYPE_MAP.put("E3828596", "pwl"); // Windows Password (pwl)
|
||||
FILE_TYPE_MAP.put("2E7261FD", "ram"); // Real Audio (ram)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,7 +85,7 @@ public class FileTypeUtil {
|
||||
* @return 之前已经存在的文件扩展名
|
||||
*/
|
||||
public static String putFileType(String fileStreamHexHead, String extName) {
|
||||
return fileTypeMap.put(fileStreamHexHead.toLowerCase(), extName);
|
||||
return FILE_TYPE_MAP.put(fileStreamHexHead.toLowerCase(), extName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,7 +95,7 @@ public class FileTypeUtil {
|
||||
* @return 移除的文件扩展名
|
||||
*/
|
||||
public static String removeFileType(String fileStreamHexHead) {
|
||||
return fileTypeMap.remove(fileStreamHexHead.toLowerCase());
|
||||
return FILE_TYPE_MAP.remove(fileStreamHexHead.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,7 +105,7 @@ public class FileTypeUtil {
|
||||
* @return 文件类型,未找到为<code>null</code>
|
||||
*/
|
||||
public static String getType(String fileStreamHexHead) {
|
||||
for (Entry<String, String> fileTypeEntry : fileTypeMap.entrySet()) {
|
||||
for (Entry<String, String> fileTypeEntry : FILE_TYPE_MAP.entrySet()) {
|
||||
if (StrUtil.startWithIgnoreCase(fileStreamHexHead, fileTypeEntry.getKey())) {
|
||||
return fileTypeEntry.getValue();
|
||||
}
|
||||
|
@ -421,6 +421,18 @@ public class IoUtil {
|
||||
|
||||
// -------------------------------------------------------------------------------------- read start
|
||||
|
||||
/**
|
||||
* 从流中读取UTF8编码的内容
|
||||
*
|
||||
* @param in 输入流
|
||||
* @return 内容
|
||||
* @throws IORuntimeException IO异常
|
||||
* @since 5.4.4
|
||||
*/
|
||||
public static String readUtf8(InputStream in) throws IORuntimeException {
|
||||
return read(in, CharsetUtil.CHARSET_UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从流中读取内容
|
||||
*
|
||||
@ -1251,7 +1263,7 @@ public class IoUtil {
|
||||
* @throws IORuntimeException IO异常
|
||||
* @since 5.4.0
|
||||
*/
|
||||
public static long checksumValue(InputStream in, Checksum checksum){
|
||||
public static long checksumValue(InputStream in, Checksum checksum) {
|
||||
return checksum(in, checksum).getValue();
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ package cn.hutool.core.io.checksum.crc16;
|
||||
*/
|
||||
public class CRC16Ansi extends CRC16Checksum{
|
||||
|
||||
private static final int wCPoly = 0xa001;
|
||||
private static final int WC_POLY = 0xa001;
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
@ -25,7 +25,7 @@ public class CRC16Ansi extends CRC16Checksum{
|
||||
int flag = wCRCin & 0x0001;
|
||||
wCRCin = wCRCin >> 1;
|
||||
if (flag == 1) {
|
||||
wCRCin ^= wCPoly;
|
||||
wCRCin ^= WC_POLY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ package cn.hutool.core.io.checksum.crc16;
|
||||
*/
|
||||
public class CRC16CCITT extends CRC16Checksum{
|
||||
|
||||
private static final int wCPoly = 0x8408;
|
||||
private static final int WC_POLY = 0x8408;
|
||||
|
||||
@Override
|
||||
public void update(int b) {
|
||||
@ -17,7 +17,7 @@ public class CRC16CCITT extends CRC16Checksum{
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if ((wCRCin & 0x0001) != 0) {
|
||||
wCRCin >>= 1;
|
||||
wCRCin ^= wCPoly;
|
||||
wCRCin ^= WC_POLY;
|
||||
} else {
|
||||
wCRCin >>= 1;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ package cn.hutool.core.io.checksum.crc16;
|
||||
*/
|
||||
public class CRC16CCITTFalse extends CRC16Checksum{
|
||||
|
||||
private static final int wCPoly = 0x1021;
|
||||
private static final int WC_POLY = 0x1021;
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
@ -28,7 +28,7 @@ public class CRC16CCITTFalse extends CRC16Checksum{
|
||||
boolean c15 = ((wCRCin >> 15 & 1) == 1);
|
||||
wCRCin <<= 1;
|
||||
if (c15 ^ bit)
|
||||
wCRCin ^= wCPoly;
|
||||
wCRCin ^= WC_POLY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ package cn.hutool.core.io.checksum.crc16;
|
||||
*/
|
||||
public class CRC16DNP extends CRC16Checksum{
|
||||
|
||||
private static final int wCPoly = 0xA6BC;
|
||||
private static final int WC_POLY = 0xA6BC;
|
||||
|
||||
@Override
|
||||
public void update(byte[] b, int off, int len) {
|
||||
@ -23,7 +23,7 @@ public class CRC16DNP extends CRC16Checksum{
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if ((wCRCin & 0x0001) != 0) {
|
||||
wCRCin >>= 1;
|
||||
wCRCin ^= wCPoly;
|
||||
wCRCin ^= WC_POLY;
|
||||
} else {
|
||||
wCRCin >>= 1;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ package cn.hutool.core.io.checksum.crc16;
|
||||
*/
|
||||
public class CRC16IBM extends CRC16Checksum{
|
||||
|
||||
private static final int wCPoly = 0xa001;
|
||||
private static final int WC_POLY = 0xa001;
|
||||
|
||||
@Override
|
||||
public void update(int b) {
|
||||
@ -17,7 +17,7 @@ public class CRC16IBM extends CRC16Checksum{
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if ((wCRCin & 0x0001) != 0) {
|
||||
wCRCin >>= 1;
|
||||
wCRCin ^= wCPoly;
|
||||
wCRCin ^= WC_POLY;
|
||||
} else {
|
||||
wCRCin >>= 1;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ package cn.hutool.core.io.checksum.crc16;
|
||||
*/
|
||||
public class CRC16Maxim extends CRC16Checksum{
|
||||
|
||||
private static final int wCPoly = 0xa001;
|
||||
private static final int WC_POLY = 0xa001;
|
||||
|
||||
@Override
|
||||
public void update(byte[] b, int off, int len) {
|
||||
@ -23,7 +23,7 @@ public class CRC16Maxim extends CRC16Checksum{
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if ((wCRCin & 0x0001) != 0) {
|
||||
wCRCin >>= 1;
|
||||
wCRCin ^= wCPoly;
|
||||
wCRCin ^= WC_POLY;
|
||||
} else {
|
||||
wCRCin >>= 1;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ package cn.hutool.core.io.checksum.crc16;
|
||||
*/
|
||||
public class CRC16Modbus extends CRC16Checksum{
|
||||
|
||||
private static final int wCPoly = 0xa001;
|
||||
private static final int WC_POLY = 0xa001;
|
||||
|
||||
@Override
|
||||
public void reset(){
|
||||
@ -23,7 +23,7 @@ public class CRC16Modbus extends CRC16Checksum{
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if ((wCRCin & 0x0001) != 0) {
|
||||
wCRCin >>= 1;
|
||||
wCRCin ^= wCPoly;
|
||||
wCRCin ^= WC_POLY;
|
||||
} else {
|
||||
wCRCin >>= 1;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ package cn.hutool.core.io.checksum.crc16;
|
||||
*/
|
||||
public class CRC16USB extends CRC16Checksum{
|
||||
|
||||
private static final int wCPoly = 0xa001;
|
||||
private static final int WC_POLY = 0xa001;
|
||||
|
||||
@Override
|
||||
public void reset(){
|
||||
@ -28,7 +28,7 @@ public class CRC16USB extends CRC16Checksum{
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if ((wCRCin & 0x0001) != 0) {
|
||||
wCRCin >>= 1;
|
||||
wCRCin ^= wCPoly;
|
||||
wCRCin ^= WC_POLY;
|
||||
} else {
|
||||
wCRCin >>= 1;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ package cn.hutool.core.io.checksum.crc16;
|
||||
*/
|
||||
public class CRC16X25 extends CRC16Checksum{
|
||||
|
||||
private static final int wCPoly = 0x8408;
|
||||
private static final int WC_POLY = 0x8408;
|
||||
|
||||
@Override
|
||||
public void reset(){
|
||||
@ -28,7 +28,7 @@ public class CRC16X25 extends CRC16Checksum{
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if ((wCRCin & 0x0001) != 0) {
|
||||
wCRCin >>= 1;
|
||||
wCRCin ^= wCPoly;
|
||||
wCRCin ^= WC_POLY;
|
||||
} else {
|
||||
wCRCin >>= 1;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ package cn.hutool.core.io.checksum.crc16;
|
||||
public class CRC16XModem extends CRC16Checksum{
|
||||
|
||||
// 0001 0000 0010 0001 (0, 5, 12)
|
||||
private static final int wCPoly = 0x1021;
|
||||
private static final int WC_POLY = 0x1021;
|
||||
|
||||
@Override
|
||||
public void update(byte[] b, int off, int len) {
|
||||
@ -25,7 +25,7 @@ public class CRC16XModem extends CRC16Checksum{
|
||||
boolean c15 = ((wCRCin >> 15 & 1) == 1);
|
||||
wCRCin <<= 1;
|
||||
if (c15 ^ bit)
|
||||
wCRCin ^= wCPoly;
|
||||
wCRCin ^= WC_POLY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,177 @@
|
||||
package cn.hutool.core.lang;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 控制台打印表格工具
|
||||
*
|
||||
* @author 孙宇
|
||||
*/
|
||||
public class ConsoleTableUtil {
|
||||
/**
|
||||
* 表格头信息
|
||||
*/
|
||||
private final List<List<String>> HEADER_LIST = new ArrayList<>();
|
||||
/**
|
||||
* 表格体信息
|
||||
*/
|
||||
private final List<List<String>> BODY_LIST = new ArrayList<>();
|
||||
/**
|
||||
* 每列最大字符个数
|
||||
*/
|
||||
private List<Integer> columnCharNumber;
|
||||
|
||||
/**
|
||||
* 测试
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
ConsoleTableUtil t = new ConsoleTableUtil();
|
||||
t.addHeader("姓名", "年龄");
|
||||
t.addBody("张三", "15");
|
||||
t.addBody("李四", "29");
|
||||
t.addBody("王二麻子", "37");
|
||||
t.print();
|
||||
|
||||
t = new ConsoleTableUtil();
|
||||
t.addHeader("体温", "占比");
|
||||
t.addHeader("℃", "%");
|
||||
t.addBody("36.8", "10");
|
||||
t.addBody("37", "5");
|
||||
t.print();
|
||||
|
||||
t = new ConsoleTableUtil();
|
||||
t.addHeader("标题1", "标题2");
|
||||
t.addBody("12345", "混合321654asdfcSDF");
|
||||
t.addBody("sd e3ee ff22", "ff值");
|
||||
t.print();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加头信息
|
||||
*
|
||||
* @param titles 列名
|
||||
* @return 自身对象
|
||||
*/
|
||||
public ConsoleTableUtil addHeader(String... titles) {
|
||||
if (columnCharNumber == null) {
|
||||
columnCharNumber = new ArrayList<>(Collections.nCopies(titles.length, 0));
|
||||
}
|
||||
List<String> l = new ArrayList<>();
|
||||
HEADER_LIST.add(l);
|
||||
fillColumns(l, titles);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加体信息
|
||||
*
|
||||
* @param values 列值
|
||||
* @return 自身对象
|
||||
*/
|
||||
public ConsoleTableUtil addBody(String... values) {
|
||||
List<String> l = new ArrayList<>();
|
||||
BODY_LIST.add(l);
|
||||
fillColumns(l, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充表格头或者体
|
||||
*
|
||||
* @param l
|
||||
* @param columns
|
||||
*/
|
||||
private void fillColumns(List<String> l, String[] columns) {
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
String column = columns[i];
|
||||
String col = Convert.toSBC(column);
|
||||
l.add(col);
|
||||
int width = col.length();
|
||||
if (width > columnCharNumber.get(i)) {
|
||||
columnCharNumber.set(i, width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表格字符串
|
||||
*
|
||||
* @return 表格字符串
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
fillBorder(sb);
|
||||
for (List<String> headers : HEADER_LIST) {
|
||||
for (int i = 0; i < headers.size(); i++) {
|
||||
if (i == 0) {
|
||||
sb.append('|');
|
||||
}
|
||||
String header = headers.get(i);
|
||||
sb.append(Convert.toSBC(" "));
|
||||
sb.append(header);
|
||||
sb.append(Convert.toSBC(" "));
|
||||
int l = header.length();
|
||||
int lw = columnCharNumber.get(i);
|
||||
if (lw > l) {
|
||||
for (int j = 0; j < (lw - l); j++) {
|
||||
sb.append(Convert.toSBC(" "));
|
||||
}
|
||||
}
|
||||
sb.append('|');
|
||||
}
|
||||
sb.append('\n');
|
||||
}
|
||||
fillBorder(sb);
|
||||
for (List<String> bodys : BODY_LIST) {
|
||||
for (int i = 0; i < bodys.size(); i++) {
|
||||
if (i == 0) {
|
||||
sb.append('|');
|
||||
}
|
||||
String body = bodys.get(i);
|
||||
sb.append(Convert.toSBC(" "));
|
||||
sb.append(body);
|
||||
sb.append(Convert.toSBC(" "));
|
||||
int l = body.length();
|
||||
int lw = columnCharNumber.get(i);
|
||||
if (lw > l) {
|
||||
for (int j = 0; j < (lw - l); j++) {
|
||||
sb.append(Convert.toSBC(" "));
|
||||
}
|
||||
}
|
||||
sb.append('|');
|
||||
}
|
||||
sb.append('\n');
|
||||
}
|
||||
fillBorder(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼装边框
|
||||
*
|
||||
* @param sb
|
||||
*/
|
||||
private void fillBorder(StringBuilder sb) {
|
||||
sb.append('*');
|
||||
for (Integer width : columnCharNumber) {
|
||||
sb.append(Convert.toSBC(StrUtil.fillAfter("", '-', width + 2)));
|
||||
sb.append('*');
|
||||
}
|
||||
sb.append('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印到控制台
|
||||
*/
|
||||
public void print() {
|
||||
Console.print(toString());
|
||||
}
|
||||
|
||||
}
|
@ -31,9 +31,9 @@ import cn.hutool.core.util.StrUtil;
|
||||
public class ObjectId {
|
||||
|
||||
/** 线程安全的下一个随机数,每次生成自增+1 */
|
||||
private static final AtomicInteger nextInc = new AtomicInteger(RandomUtil.randomInt());
|
||||
private static final AtomicInteger NEXT_INC = new AtomicInteger(RandomUtil.randomInt());
|
||||
/** 机器信息 */
|
||||
private static final int machine = getMachinePiece() | getProcessPiece();
|
||||
private static final int MACHINE = getMachinePiece() | getProcessPiece();
|
||||
|
||||
/**
|
||||
* 给定的字符串是否为有效的ObjectId
|
||||
@ -77,8 +77,8 @@ public class ObjectId {
|
||||
public static byte[] nextBytes() {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(new byte[12]);
|
||||
bb.putInt((int) DateUtil.currentSeconds());// 4位
|
||||
bb.putInt(machine);// 4位
|
||||
bb.putInt(nextInc.getAndIncrement());// 4位
|
||||
bb.putInt(MACHINE);// 4位
|
||||
bb.putInt(NEXT_INC.getAndIncrement());// 4位
|
||||
|
||||
return bb.array();
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public class UUID implements java.io.Serializable, Comparable<UUID> {
|
||||
* @author looly
|
||||
*/
|
||||
private static class Holder {
|
||||
static final SecureRandom numberGenerator = RandomUtil.getSecureRandom();
|
||||
static final SecureRandom NUMBER_GENERATOR = RandomUtil.getSecureRandom();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,7 +117,7 @@ public class UUID implements java.io.Serializable, Comparable<UUID> {
|
||||
* @return 随机生成的 {@code UUID}
|
||||
*/
|
||||
public static UUID randomUUID(boolean isSecure) {
|
||||
final Random ng = isSecure ? Holder.numberGenerator : RandomUtil.getRandom();
|
||||
final Random ng = isSecure ? Holder.NUMBER_GENERATOR : RandomUtil.getRandom();
|
||||
|
||||
final byte[] randomBytes = new byte[16];
|
||||
ng.nextBytes(randomBytes);
|
||||
|
@ -17,7 +17,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class ActualTypeMapperPool {
|
||||
|
||||
private static final SimpleCache<Type, Map<Type, Type>> cache = new SimpleCache<>();
|
||||
private static final SimpleCache<Type, Map<Type, Type>> CACHE = new SimpleCache<>();
|
||||
|
||||
/**
|
||||
* 获取泛型变量和泛型实际类型的对应关系Map
|
||||
@ -26,7 +26,7 @@ public class ActualTypeMapperPool {
|
||||
* @return 泛型对应关系Map
|
||||
*/
|
||||
public static Map<Type, Type> get(Type type) {
|
||||
return cache.get(type, () -> createTypeMap(type));
|
||||
return CACHE.get(type, () -> createTypeMap(type));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,7 +67,7 @@ public class Money implements Serializable, Comparable<Money> {
|
||||
* 此处,“分”是指货币的最小单位,“元”是货币的最常用单位,
|
||||
* 不同的币种有不同的元/分换算比例,如人民币是100,而日元为1。
|
||||
*/
|
||||
private static final int[] centFactors = new int[]{1, 10, 100, 1000};
|
||||
private static final int[] CENT_FACTORS = new int[]{1, 10, 100, 1000};
|
||||
|
||||
/**
|
||||
* 金额,以分为单位。
|
||||
@ -318,7 +318,7 @@ public class Money implements Serializable, Comparable<Money> {
|
||||
* @return 本货币币种的元/分换算比率。
|
||||
*/
|
||||
public int getCentFactor() {
|
||||
return centFactors[currency.getDefaultFractionDigits()];
|
||||
return CENT_FACTORS[currency.getDefaultFractionDigits()];
|
||||
}
|
||||
|
||||
// 基本对象方法 ===================================================
|
||||
|
@ -11,41 +11,41 @@ import java.util.Map;
|
||||
*/
|
||||
public class MaskBit {
|
||||
|
||||
private static final Map<Integer, String> maskBitMap;
|
||||
private static final Map<Integer, String> MASK_BIT_MAP;
|
||||
static {
|
||||
maskBitMap = new HashMap<>(32);
|
||||
maskBitMap.put(1, "128.0.0.0");
|
||||
maskBitMap.put(2, "192.0.0.0");
|
||||
maskBitMap.put(3, "224.0.0.0");
|
||||
maskBitMap.put(4, "240.0.0.0");
|
||||
maskBitMap.put(5, "248.0.0.0");
|
||||
maskBitMap.put(6, "252.0.0.0");
|
||||
maskBitMap.put(7, "254.0.0.0");
|
||||
maskBitMap.put(8, "255.0.0.0");
|
||||
maskBitMap.put(9, "255.128.0.0");
|
||||
maskBitMap.put(10, "255.192.0.0");
|
||||
maskBitMap.put(11, "255.224.0.0");
|
||||
maskBitMap.put(12, "255.240.0.0");
|
||||
maskBitMap.put(13, "255.248.0.0");
|
||||
maskBitMap.put(14, "255.252.0.0");
|
||||
maskBitMap.put(15, "255.254.0.0");
|
||||
maskBitMap.put(16, "255.255.0.0");
|
||||
maskBitMap.put(17, "255.255.128.0");
|
||||
maskBitMap.put(18, "255.255.192.0");
|
||||
maskBitMap.put(19, "255.255.224.0");
|
||||
maskBitMap.put(20, "255.255.240.0");
|
||||
maskBitMap.put(21, "255.255.248.0");
|
||||
maskBitMap.put(22, "255.255.252.0");
|
||||
maskBitMap.put(23, "255.255.254.0");
|
||||
maskBitMap.put(24, "255.255.255.0");
|
||||
maskBitMap.put(25, "255.255.255.128");
|
||||
maskBitMap.put(26, "255.255.255.192");
|
||||
maskBitMap.put(27, "255.255.255.224");
|
||||
maskBitMap.put(28, "255.255.255.240");
|
||||
maskBitMap.put(29, "255.255.255.248");
|
||||
maskBitMap.put(30, "255.255.255.252");
|
||||
maskBitMap.put(31, "255.255.255.254");
|
||||
maskBitMap.put(32, "255.255.255.255");
|
||||
MASK_BIT_MAP = new HashMap<>(32);
|
||||
MASK_BIT_MAP.put(1, "128.0.0.0");
|
||||
MASK_BIT_MAP.put(2, "192.0.0.0");
|
||||
MASK_BIT_MAP.put(3, "224.0.0.0");
|
||||
MASK_BIT_MAP.put(4, "240.0.0.0");
|
||||
MASK_BIT_MAP.put(5, "248.0.0.0");
|
||||
MASK_BIT_MAP.put(6, "252.0.0.0");
|
||||
MASK_BIT_MAP.put(7, "254.0.0.0");
|
||||
MASK_BIT_MAP.put(8, "255.0.0.0");
|
||||
MASK_BIT_MAP.put(9, "255.128.0.0");
|
||||
MASK_BIT_MAP.put(10, "255.192.0.0");
|
||||
MASK_BIT_MAP.put(11, "255.224.0.0");
|
||||
MASK_BIT_MAP.put(12, "255.240.0.0");
|
||||
MASK_BIT_MAP.put(13, "255.248.0.0");
|
||||
MASK_BIT_MAP.put(14, "255.252.0.0");
|
||||
MASK_BIT_MAP.put(15, "255.254.0.0");
|
||||
MASK_BIT_MAP.put(16, "255.255.0.0");
|
||||
MASK_BIT_MAP.put(17, "255.255.128.0");
|
||||
MASK_BIT_MAP.put(18, "255.255.192.0");
|
||||
MASK_BIT_MAP.put(19, "255.255.224.0");
|
||||
MASK_BIT_MAP.put(20, "255.255.240.0");
|
||||
MASK_BIT_MAP.put(21, "255.255.248.0");
|
||||
MASK_BIT_MAP.put(22, "255.255.252.0");
|
||||
MASK_BIT_MAP.put(23, "255.255.254.0");
|
||||
MASK_BIT_MAP.put(24, "255.255.255.0");
|
||||
MASK_BIT_MAP.put(25, "255.255.255.128");
|
||||
MASK_BIT_MAP.put(26, "255.255.255.192");
|
||||
MASK_BIT_MAP.put(27, "255.255.255.224");
|
||||
MASK_BIT_MAP.put(28, "255.255.255.240");
|
||||
MASK_BIT_MAP.put(29, "255.255.255.248");
|
||||
MASK_BIT_MAP.put(30, "255.255.255.252");
|
||||
MASK_BIT_MAP.put(31, "255.255.255.254");
|
||||
MASK_BIT_MAP.put(32, "255.255.255.255");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,6 +55,6 @@ public class MaskBit {
|
||||
* @return 掩码
|
||||
*/
|
||||
public static String get(int maskBit) {
|
||||
return maskBitMap.get(maskBit);
|
||||
return MASK_BIT_MAP.get(maskBit);
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ public class NetUtil {
|
||||
|
||||
public final static String LOCAL_IP = "127.0.0.1";
|
||||
|
||||
public static String localhostName;
|
||||
|
||||
/**
|
||||
* 默认最小端口,1024
|
||||
*/
|
||||
@ -533,6 +535,29 @@ public class NetUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主机名称,一次获取会缓存名称
|
||||
*
|
||||
* @return 主机名称
|
||||
* @since 5.4.4
|
||||
*/
|
||||
public static String getLocalHostName() {
|
||||
if (StrUtil.isNotBlank(localhostName)) {
|
||||
return localhostName;
|
||||
}
|
||||
|
||||
final InetAddress localhost = getLocalhost();
|
||||
if(null != localhost){
|
||||
String name = localhost.getHostName();
|
||||
if(StrUtil.isEmpty(name)){
|
||||
name = localhost.getHostAddress();
|
||||
}
|
||||
localhostName = name;
|
||||
}
|
||||
|
||||
return localhostName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 {@link InetSocketAddress}
|
||||
*
|
||||
|
@ -20,12 +20,12 @@ import cn.hutool.core.swing.clipboard.ClipboardUtil;
|
||||
*/
|
||||
public class RobotUtil {
|
||||
|
||||
private static final Robot robot;
|
||||
private static final Robot ROBOT;
|
||||
private static int delay;
|
||||
|
||||
static {
|
||||
try {
|
||||
robot = new Robot();
|
||||
ROBOT = new Robot();
|
||||
} catch (AWTException e) {
|
||||
throw new UtilException(e);
|
||||
}
|
||||
@ -50,7 +50,7 @@ public class RobotUtil {
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static void mouseMove(int x, int y) {
|
||||
robot.mouseMove(x, y);
|
||||
ROBOT.mouseMove(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,8 +60,8 @@ public class RobotUtil {
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static void click() {
|
||||
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||
ROBOT.mousePress(InputEvent.BUTTON1_MASK);
|
||||
ROBOT.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||
delay();
|
||||
}
|
||||
|
||||
@ -72,8 +72,8 @@ public class RobotUtil {
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static void rightClick() {
|
||||
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||
ROBOT.mousePress(InputEvent.BUTTON1_MASK);
|
||||
ROBOT.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||
delay();
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ public class RobotUtil {
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static void mouseWheel(int wheelAmt) {
|
||||
robot.mouseWheel(wheelAmt);
|
||||
ROBOT.mouseWheel(wheelAmt);
|
||||
delay();
|
||||
}
|
||||
|
||||
@ -97,8 +97,8 @@ public class RobotUtil {
|
||||
*/
|
||||
public static void keyClick(int... keyCodes) {
|
||||
for (int keyCode : keyCodes) {
|
||||
robot.keyPress(keyCode);
|
||||
robot.keyRelease(keyCode);
|
||||
ROBOT.keyPress(keyCode);
|
||||
ROBOT.keyRelease(keyCode);
|
||||
}
|
||||
delay();
|
||||
}
|
||||
@ -120,10 +120,10 @@ public class RobotUtil {
|
||||
* @param key 按键
|
||||
*/
|
||||
public static void keyPressWithShift(int key) {
|
||||
robot.keyPress(KeyEvent.VK_SHIFT);
|
||||
robot.keyPress(key);
|
||||
robot.keyRelease(key);
|
||||
robot.keyRelease(KeyEvent.VK_SHIFT);
|
||||
ROBOT.keyPress(KeyEvent.VK_SHIFT);
|
||||
ROBOT.keyPress(key);
|
||||
ROBOT.keyRelease(key);
|
||||
ROBOT.keyRelease(KeyEvent.VK_SHIFT);
|
||||
delay();
|
||||
}
|
||||
|
||||
@ -133,10 +133,10 @@ public class RobotUtil {
|
||||
* @param key 按键
|
||||
*/
|
||||
public static void keyPressWithCtrl(int key) {
|
||||
robot.keyPress(KeyEvent.VK_CONTROL);
|
||||
robot.keyPress(key);
|
||||
robot.keyRelease(key);
|
||||
robot.keyRelease(KeyEvent.VK_CONTROL);
|
||||
ROBOT.keyPress(KeyEvent.VK_CONTROL);
|
||||
ROBOT.keyPress(key);
|
||||
ROBOT.keyRelease(key);
|
||||
ROBOT.keyRelease(KeyEvent.VK_CONTROL);
|
||||
delay();
|
||||
}
|
||||
|
||||
@ -146,10 +146,10 @@ public class RobotUtil {
|
||||
* @param key 按键
|
||||
*/
|
||||
public static void keyPressWithAlt(int key) {
|
||||
robot.keyPress(KeyEvent.VK_ALT);
|
||||
robot.keyPress(key);
|
||||
robot.keyRelease(key);
|
||||
robot.keyRelease(KeyEvent.VK_ALT);
|
||||
ROBOT.keyPress(KeyEvent.VK_ALT);
|
||||
ROBOT.keyPress(key);
|
||||
ROBOT.keyRelease(key);
|
||||
ROBOT.keyRelease(KeyEvent.VK_ALT);
|
||||
delay();
|
||||
}
|
||||
|
||||
@ -180,7 +180,7 @@ public class RobotUtil {
|
||||
* @return 截屏的图片
|
||||
*/
|
||||
public static BufferedImage captureScreen(Rectangle screenRect) {
|
||||
return robot.createScreenCapture(screenRect);
|
||||
return ROBOT.createScreenCapture(screenRect);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,7 +200,7 @@ public class RobotUtil {
|
||||
*/
|
||||
private static void delay() {
|
||||
if (delay > 0) {
|
||||
robot.delay(delay);
|
||||
ROBOT.delay(delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import cn.hutool.core.text.replacer.ReplacerChain;
|
||||
|
||||
/**
|
||||
* HTML4的ESCAPE
|
||||
* 参考:Commons Lang3
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
|
@ -15,11 +15,14 @@ public class Html4Unescape extends ReplacerChain {
|
||||
protected static final String[][] BASIC_UNESCAPE = InternalEscapeUtil.invert(Html4Escape.BASIC_ESCAPE);
|
||||
protected static final String[][] ISO8859_1_UNESCAPE = InternalEscapeUtil.invert(Html4Escape.ISO8859_1_ESCAPE);
|
||||
protected static final String[][] HTML40_EXTENDED_UNESCAPE = InternalEscapeUtil.invert(Html4Escape.HTML40_EXTENDED_ESCAPE);
|
||||
// issue#1118
|
||||
protected static final String[][] OTHER_UNESCAPE = new String[][]{new String[]{"'", "'"}};
|
||||
|
||||
public Html4Unescape() {
|
||||
addChain(new LookupReplacer(BASIC_UNESCAPE));
|
||||
addChain(new LookupReplacer(ISO8859_1_UNESCAPE));
|
||||
addChain(new LookupReplacer(HTML40_EXTENDED_UNESCAPE));
|
||||
addChain(new LookupReplacer(OTHER_UNESCAPE));
|
||||
addChain(new NumericEntityUnescaper());
|
||||
}
|
||||
}
|
||||
|
@ -11,24 +11,44 @@ import cn.hutool.core.text.ASCIIStrCache;
|
||||
*/
|
||||
public class CharUtil {
|
||||
|
||||
/** 字符常量:空格符 ' ' */
|
||||
public static final char SPACE = ' ';
|
||||
/** 字符常量:制表符 \t */
|
||||
public static final char TAB = ' ';
|
||||
/** 字符常量:点 . */
|
||||
public static final char DOT = '.';
|
||||
/** 字符常量:斜杠 / */
|
||||
public static final char SLASH = '/';
|
||||
/** 字符常量:反斜杠 \ */
|
||||
public static final char BACKSLASH = '\\';
|
||||
/** 字符常量:回车符 \r */
|
||||
public static final char CR = '\r';
|
||||
/** 字符常量:换行符 \n */
|
||||
public static final char LF = '\n';
|
||||
public static final char UNDERLINE = '_';
|
||||
/** 字符常量:连接符 - */
|
||||
public static final char DASHED = '-';
|
||||
/** 字符常量:下划线 _ */
|
||||
public static final char UNDERLINE = '_';
|
||||
/** 字符常量:逗号 , */
|
||||
public static final char COMMA = ',';
|
||||
/** 字符常量:花括号(左) { */
|
||||
public static final char DELIM_START = '{';
|
||||
/** 字符常量:花括号(右) } */
|
||||
public static final char DELIM_END = '}';
|
||||
/** 字符常量:中括号(左) [ */
|
||||
public static final char BRACKET_START = '[';
|
||||
/** 字符常量:中括号(右) ] */
|
||||
public static final char BRACKET_END = ']';
|
||||
public static final char COLON = ':';
|
||||
/** 字符常量:双引号 : */
|
||||
public static final char DOUBLE_QUOTES = '"';
|
||||
/** 字符常量:单引号 ' */
|
||||
public static final char SINGLE_QUOTE = '\'';
|
||||
/** 字符常量:与 & */
|
||||
public static final char AMP = '&';
|
||||
/** 字符常量:冒号 : */
|
||||
public static final char COLON = ':';
|
||||
/** 字符常量:艾特 @ */
|
||||
public static final char AT = '@';
|
||||
|
||||
/**
|
||||
* 是否为ASCII字符,ASCII字符位于0~127之间
|
||||
|
@ -33,13 +33,13 @@ public class ClassLoaderUtil {
|
||||
private static final char INNER_CLASS_SEPARATOR = '$';
|
||||
|
||||
/** 原始类型名和其class对应表,例如:int =》 int.class */
|
||||
private static final Map<String, Class<?>> primitiveTypeNameMap = new ConcurrentHashMap<>(32);
|
||||
private static final SimpleCache<String, Class<?>> classCache = new SimpleCache<>();
|
||||
private static final Map<String, Class<?>> PRIMITIVE_TYPE_NAME_MAP = new ConcurrentHashMap<>(32);
|
||||
private static final SimpleCache<String, Class<?>> CLASS_CACHE = new SimpleCache<>();
|
||||
|
||||
static {
|
||||
List<Class<?>> primitiveTypes = new ArrayList<>(32);
|
||||
// 加入原始类型
|
||||
primitiveTypes.addAll(BasicType.primitiveWrapperMap.keySet());
|
||||
primitiveTypes.addAll(BasicType.PRIMITIVE_WRAPPER_MAP.keySet());
|
||||
// 加入原始类型数组类型
|
||||
primitiveTypes.add(boolean[].class);
|
||||
primitiveTypes.add(byte[].class);
|
||||
@ -51,7 +51,7 @@ public class ClassLoaderUtil {
|
||||
primitiveTypes.add(short[].class);
|
||||
primitiveTypes.add(void.class);
|
||||
for (Class<?> primitiveType : primitiveTypes) {
|
||||
primitiveTypeNameMap.put(primitiveType.getName(), primitiveType);
|
||||
PRIMITIVE_TYPE_NAME_MAP.put(primitiveType.getName(), primitiveType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ public class ClassLoaderUtil {
|
||||
// 加载原始类型和缓存中的类
|
||||
Class<?> clazz = loadPrimitiveClass(name);
|
||||
if (clazz == null) {
|
||||
clazz = classCache.get(name);
|
||||
clazz = CLASS_CACHE.get(name);
|
||||
}
|
||||
if (clazz != null) {
|
||||
return clazz;
|
||||
@ -188,7 +188,7 @@ public class ClassLoaderUtil {
|
||||
}
|
||||
|
||||
// 加入缓存并返回
|
||||
return classCache.put(name, clazz);
|
||||
return CLASS_CACHE.put(name, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -202,7 +202,7 @@ public class ClassLoaderUtil {
|
||||
if (StrUtil.isNotBlank(name)) {
|
||||
name = name.trim();
|
||||
if (name.length() <= 8) {
|
||||
result = primitiveTypeNameMap.get(name);
|
||||
result = PRIMITIVE_TYPE_NAME_MAP.get(name);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -713,7 +713,7 @@ public class ClassUtil {
|
||||
if (null == clazz) {
|
||||
return false;
|
||||
}
|
||||
return BasicType.wrapperPrimitiveMap.containsKey(clazz);
|
||||
return BasicType.WRAPPER_PRIMITIVE_MAP.containsKey(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -798,11 +798,11 @@ public class ClassUtil {
|
||||
// 基本类型
|
||||
if (targetType.isPrimitive()) {
|
||||
// 原始类型
|
||||
Class<?> resolvedPrimitive = BasicType.wrapperPrimitiveMap.get(sourceType);
|
||||
Class<?> resolvedPrimitive = BasicType.WRAPPER_PRIMITIVE_MAP.get(sourceType);
|
||||
return targetType.equals(resolvedPrimitive);
|
||||
} else {
|
||||
// 包装类型
|
||||
Class<?> resolvedWrapper = BasicType.primitiveWrapperMap.get(sourceType);
|
||||
Class<?> resolvedWrapper = BasicType.PRIMITIVE_WRAPPER_MAP.get(sourceType);
|
||||
return resolvedWrapper != null && targetType.isAssignableFrom(resolvedWrapper);
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public class IdcardUtil {
|
||||
/**
|
||||
* 每位加权因子
|
||||
*/
|
||||
private static final int[] power = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
|
||||
private static final int[] POWER = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
|
||||
/**
|
||||
* 省市代码表
|
||||
*/
|
||||
@ -602,9 +602,9 @@ public class IdcardUtil {
|
||||
*/
|
||||
private static int getPowerSum(char[] iArr) {
|
||||
int iSum = 0;
|
||||
if (power.length == iArr.length) {
|
||||
if (POWER.length == iArr.length) {
|
||||
for (int i = 0; i < iArr.length; i++) {
|
||||
iSum += Integer.parseInt(String.valueOf(iArr[i])) * power[i];
|
||||
iSum += Integer.parseInt(String.valueOf(iArr[i])) * POWER[i];
|
||||
}
|
||||
}
|
||||
return iSum;
|
||||
|
@ -134,7 +134,7 @@ public class NumberUtil {
|
||||
}
|
||||
|
||||
Number value = values[0];
|
||||
BigDecimal result = new BigDecimal(null == value ? "0" : value.toString());
|
||||
BigDecimal result = null == value ? BigDecimal.ZERO : new BigDecimal(value.toString());
|
||||
for (int i = 1; i < values.length; i++) {
|
||||
value = values[i];
|
||||
if (null != value) {
|
||||
@ -158,7 +158,7 @@ public class NumberUtil {
|
||||
}
|
||||
|
||||
String value = values[0];
|
||||
BigDecimal result = new BigDecimal(null == value ? "0" : value);
|
||||
BigDecimal result = null == value ? BigDecimal.ZERO : new BigDecimal(value);
|
||||
for (int i = 1; i < values.length; i++) {
|
||||
value = values[i];
|
||||
if (null != value) {
|
||||
@ -274,7 +274,7 @@ public class NumberUtil {
|
||||
}
|
||||
|
||||
Number value = values[0];
|
||||
BigDecimal result = new BigDecimal(null == value ? "0" : value.toString());
|
||||
BigDecimal result = null == value ? BigDecimal.ZERO : new BigDecimal(value.toString());
|
||||
for (int i = 1; i < values.length; i++) {
|
||||
value = values[i];
|
||||
if (null != value) {
|
||||
@ -298,7 +298,7 @@ public class NumberUtil {
|
||||
}
|
||||
|
||||
String value = values[0];
|
||||
BigDecimal result = new BigDecimal(null == value ? "0" : value);
|
||||
BigDecimal result = null == value ? BigDecimal.ZERO : new BigDecimal(value);
|
||||
for (int i = 1; i < values.length; i++) {
|
||||
value = values[i];
|
||||
if (null != value) {
|
||||
@ -410,15 +410,15 @@ public class NumberUtil {
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static BigDecimal mul(Number... values) {
|
||||
if (ArrayUtil.isEmpty(values)) {
|
||||
if (ArrayUtil.isEmpty(values) || ArrayUtil.hasNull(values)) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
Number value = values[0];
|
||||
BigDecimal result = new BigDecimal(null == value ? "0" : value.toString());
|
||||
BigDecimal result = new BigDecimal(value.toString());
|
||||
for (int i = 1; i < values.length; i++) {
|
||||
value = values[i];
|
||||
result = result.multiply(new BigDecimal(null == value ? "0" : value.toString()));
|
||||
result = result.multiply(new BigDecimal(value.toString()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -444,18 +444,15 @@ public class NumberUtil {
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static BigDecimal mul(String... values) {
|
||||
if (ArrayUtil.isEmpty(values)) {
|
||||
if (ArrayUtil.isEmpty(values) || ArrayUtil.hasNull(values)) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
String value = values[0];
|
||||
BigDecimal result = new BigDecimal(null == value ? "0" : value);
|
||||
BigDecimal result =new BigDecimal(values[0]);
|
||||
for (int i = 1; i < values.length; i++) {
|
||||
value = values[i];
|
||||
if (null != value) {
|
||||
result = result.multiply(new BigDecimal(value));
|
||||
}
|
||||
result = result.multiply(new BigDecimal(values[i]));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -468,17 +465,13 @@ public class NumberUtil {
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static BigDecimal mul(BigDecimal... values) {
|
||||
if (ArrayUtil.isEmpty(values)) {
|
||||
if (ArrayUtil.isEmpty(values) || ArrayUtil.hasNull(values)) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
BigDecimal value = values[0];
|
||||
BigDecimal result = null == value ? BigDecimal.ZERO : value;
|
||||
BigDecimal result = values[0];
|
||||
for (int i = 1; i < values.length; i++) {
|
||||
value = values[i];
|
||||
if (null != value) {
|
||||
result = result.multiply(value);
|
||||
}
|
||||
result = result.multiply(values[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -1427,13 +1420,13 @@ public class NumberUtil {
|
||||
// ------------------------------------------------------------------------------------------- others
|
||||
|
||||
/**
|
||||
* 计算阶乘
|
||||
* 计算范围阶乘
|
||||
* <p>
|
||||
* n! = n * (n-1) * ... * end
|
||||
* factorial(start, end) = start * (start - 1) * ... * (end - 1)
|
||||
* </p>
|
||||
*
|
||||
* @param start 阶乘起始
|
||||
* @param end 阶乘结束,必须小于起始
|
||||
* @param start 阶乘起始(包含)
|
||||
* @param end 阶乘结束,必须小于起始(不包括)
|
||||
* @return 结果
|
||||
* @since 4.1.0
|
||||
*/
|
||||
@ -1744,6 +1737,7 @@ public class NumberUtil {
|
||||
public static boolean equals(BigDecimal bigNum1, BigDecimal bigNum2) {
|
||||
//noinspection NumberEquality
|
||||
if (bigNum1 == bigNum2){
|
||||
// 如果用户传入同一对象,省略compareTo以提高性能。
|
||||
return true;
|
||||
}
|
||||
if (bigNum1==null || bigNum2==null){
|
||||
@ -2192,6 +2186,17 @@ public class NumberUtil {
|
||||
public static BigDecimal pow(BigDecimal number, int n) {
|
||||
return number.pow(n);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断一个整数是否是2的幂
|
||||
*
|
||||
* @param n 待验证的整数
|
||||
* @return 如果n是2的幂返回true, 反之返回false
|
||||
*/
|
||||
public static boolean isPowerOfTwo(long n) {
|
||||
return (n > 0) && ((n & (n - 1)) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析转换数字字符串为int型数字,规则如下:
|
||||
|
@ -160,9 +160,10 @@ public class PageUtil {
|
||||
* @return 分页条
|
||||
*/
|
||||
public static int[] rainbow(int pageNo, int totalPage, int displayCount) {
|
||||
boolean isEven = displayCount % 2 == 0;
|
||||
int left = displayCount / 2;
|
||||
int right = displayCount / 2;
|
||||
// displayCount % 2
|
||||
boolean isEven = (displayCount & 1) == 0;
|
||||
int left = displayCount >> 1;
|
||||
int right = displayCount >> 1;
|
||||
|
||||
int length = displayCount;
|
||||
if (isEven) {
|
||||
|
@ -34,7 +34,7 @@ public class ServiceLoaderUtil {
|
||||
while (iterator.hasNext()) {
|
||||
try {
|
||||
return iterator.next();
|
||||
} catch (ServiceConfigurationError e) {
|
||||
} catch (ServiceConfigurationError ignore) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@ -76,7 +76,7 @@ public class ServiceLoaderUtil {
|
||||
* @return 服务接口实现列表
|
||||
*/
|
||||
public static <T> ServiceLoader<T> load(Class<T> clazz, ClassLoader loader) {
|
||||
return ServiceLoader.load(clazz, loader);
|
||||
return ServiceLoader.load(clazz, ObjectUtil.defaultIfNull(loader, ClassLoaderUtil.getClassLoader()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,6 +101,6 @@ public class ServiceLoaderUtil {
|
||||
* @since 5.4.2
|
||||
*/
|
||||
public static <T> List<T> loadList(Class<T> clazz, ClassLoader loader) {
|
||||
return ListUtil.list(false, load(clazz));
|
||||
return ListUtil.list(false, load(clazz, loader));
|
||||
}
|
||||
}
|
||||
|
@ -34,60 +34,125 @@ public class StrUtil {
|
||||
|
||||
public static final int INDEX_NOT_FOUND = -1;
|
||||
|
||||
/** 字符常量:空格符 ' ' */
|
||||
public static final char C_SPACE = CharUtil.SPACE;
|
||||
/** 字符常量:制表符 \t */
|
||||
public static final char C_TAB = CharUtil.TAB;
|
||||
/** 字符常量:点 . */
|
||||
public static final char C_DOT = CharUtil.DOT;
|
||||
/** 字符常量:斜杠 / */
|
||||
public static final char C_SLASH = CharUtil.SLASH;
|
||||
/** 字符常量:反斜杠 \ */
|
||||
public static final char C_BACKSLASH = CharUtil.BACKSLASH;
|
||||
/** 字符常量:回车符 \r */
|
||||
public static final char C_CR = CharUtil.CR;
|
||||
/** 字符常量:换行符 \n */
|
||||
public static final char C_LF = CharUtil.LF;
|
||||
/** 字符常量:下划线 _ */
|
||||
public static final char C_UNDERLINE = CharUtil.UNDERLINE;
|
||||
/** 字符常量:逗号 , */
|
||||
public static final char C_COMMA = CharUtil.COMMA;
|
||||
/** 字符常量:花括号(左) { */
|
||||
public static final char C_DELIM_START = CharUtil.DELIM_START;
|
||||
/** 字符常量:花括号(右) } */
|
||||
public static final char C_DELIM_END = CharUtil.DELIM_END;
|
||||
/** 字符常量:中括号(左) [ */
|
||||
public static final char C_BRACKET_START = CharUtil.BRACKET_START;
|
||||
/** 字符常量:中括号(右) ] */
|
||||
public static final char C_BRACKET_END = CharUtil.BRACKET_END;
|
||||
/** 字符常量:冒号 : */
|
||||
public static final char C_COLON = CharUtil.COLON;
|
||||
/** 字符常量:艾特 @ */
|
||||
public static final char C_AT = CharUtil.AT;
|
||||
|
||||
/** 字符串常量:空格符 ' ' */
|
||||
public static final String SPACE = " ";
|
||||
/** 字符串常量:制表符 \t */
|
||||
public static final String TAB = " ";
|
||||
/** 字符串常量:点 . */
|
||||
public static final String DOT = ".";
|
||||
/**
|
||||
* 字符串常量:双点 ..
|
||||
* 用途:作为指向上级文件夹的路径 "../path"
|
||||
*/
|
||||
public static final String DOUBLE_DOT = "..";
|
||||
/** 字符串常量:斜杠 / */
|
||||
public static final String SLASH = "/";
|
||||
/** 字符串常量:反斜杠 \ */
|
||||
public static final String BACKSLASH = "\\";
|
||||
/** 字符串常量:空字符串 "" */
|
||||
public static final String EMPTY = "";
|
||||
/**
|
||||
* 字符串常量:"null"
|
||||
* 注意:"null" != null
|
||||
*/
|
||||
public static final String NULL = "null";
|
||||
/**
|
||||
* 字符串常量:回车符 \r
|
||||
* 解释:该字符常用于表示 Linux 系统和 MacOS 系统下的文本换行
|
||||
*/
|
||||
public static final String CR = "\r";
|
||||
/** 字符串常量:换行符 \n */
|
||||
public static final String LF = "\n";
|
||||
/**
|
||||
* 字符串常量:Windows 换行 \r\n
|
||||
* 解释:该字符串常用于表示 Windows 系统下的文本换行
|
||||
*/
|
||||
public static final String CRLF = "\r\n";
|
||||
/** 字符串常量:下划线 _ */
|
||||
public static final String UNDERLINE = "_";
|
||||
/** 字符串常量:减号(中划线) - */
|
||||
public static final String DASHED = "-";
|
||||
/** 字符串常量:逗号 , */
|
||||
public static final String COMMA = ",";
|
||||
/** 字符串常量:花括号(左) { */
|
||||
public static final String DELIM_START = "{";
|
||||
/** 字符串常量:花括号(右) } */
|
||||
public static final String DELIM_END = "}";
|
||||
/** 字符串常量:中括号(左) [ */
|
||||
public static final String BRACKET_START = "[";
|
||||
/** 字符串常量:中括号(右) ] */
|
||||
public static final String BRACKET_END = "]";
|
||||
/** 字符串常量:冒号 : */
|
||||
public static final String COLON = ":";
|
||||
/** 字符串常量:艾特 @ */
|
||||
public static final String AT = "@";
|
||||
|
||||
/** 字符串常量:HTML 空格转义 */
|
||||
public static final String HTML_NBSP = " ";
|
||||
/** 字符串常量:HTML And 符转义 & */
|
||||
public static final String HTML_AMP = "&";
|
||||
/** 字符串常量:HTML 双引号转义 " */
|
||||
public static final String HTML_QUOTE = """;
|
||||
/** 字符串常量:HTML 单引号转义 ' */
|
||||
public static final String HTML_APOS = "'";
|
||||
/** 字符串常量:HTML 小于号转义 < */
|
||||
public static final String HTML_LT = "<";
|
||||
/** 字符串常量:HTML 大于号转义 > */
|
||||
public static final String HTML_GT = ">";
|
||||
|
||||
/** 字符串常量:空 JSON "{}" */
|
||||
public static final String EMPTY_JSON = "{}";
|
||||
|
||||
// ------------------------------------------------------------------------ Blank
|
||||
|
||||
/**
|
||||
* 字符串是否为空白 空白的定义如下: <br>
|
||||
* 1、为null <br>
|
||||
* 2、为不可见字符(如空格)<br>
|
||||
* 3、""<br>
|
||||
* <p>字符串是否为空白,空白的定义如下:</p>
|
||||
* <ol>
|
||||
* <li>{@code null}</li>
|
||||
* <li>空字符串:{@code ""}</li>
|
||||
* <li>空格、全角空格、制表符、换行符,等不可见字符</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>例:</p>
|
||||
* <ul>
|
||||
* <li>{@code StrUtil.isBlank(null) // true}</li>
|
||||
* <li>{@code StrUtil.isBlank("") // true}</li>
|
||||
* <li>{@code StrUtil.isBlank(" \t\n") // true}</li>
|
||||
* <li>{@code StrUtil.isBlank("abc") // false}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param str 被检测的字符串
|
||||
* @return 是否为空
|
||||
* @return 若为空白,则返回 true
|
||||
*/
|
||||
public static boolean isBlank(CharSequence str) {
|
||||
int length;
|
||||
@ -107,13 +172,25 @@ public class StrUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果对象是字符串是否为空白,空白的定义如下: <br>
|
||||
* 1、为null <br>
|
||||
* 2、为不可见字符(如空格)<br>
|
||||
* 3、""<br>
|
||||
* <p>如果对象是字符串是否为空白,空白的定义如下:</p>
|
||||
* <ol>
|
||||
* <li>{@code null}</li>
|
||||
* <li>空字符串:{@code ""}</li>
|
||||
* <li>空格、全角空格、制表符、换行符,等不可见字符</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>例:</p>
|
||||
* <ul>
|
||||
* <li>{@code StrUtil.isBlankIfStr(null) // true}</li>
|
||||
* <li>{@code StrUtil.isBlankIfStr("") // true}</li>
|
||||
* <li>{@code StrUtil.isBlankIfStr(" \t\n") // true}</li>
|
||||
* <li>{@code StrUtil.isBlankIfStr("abc") // false}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return 如果为字符串是否为空串
|
||||
*
|
||||
* @see StrUtil#isBlank(CharSequence)
|
||||
* @since 3.3.0
|
||||
*/
|
||||
public static boolean isBlankIfStr(Object obj) {
|
||||
@ -4150,7 +4227,7 @@ public class StrUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算连个字符串的相似度百分比
|
||||
* 计算两个字符串的相似度百分比
|
||||
*
|
||||
* @param str1 字符串1
|
||||
* @param str2 字符串2
|
||||
|
@ -483,13 +483,7 @@ public class URLUtil {
|
||||
* @throws UtilException 包装URISyntaxException
|
||||
*/
|
||||
public static String getPath(String uriStr) {
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(uriStr);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new UtilException(e);
|
||||
}
|
||||
return uri.getPath();
|
||||
return toURI(uriStr).getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -509,7 +503,7 @@ public class URLUtil {
|
||||
String path = null;
|
||||
try {
|
||||
// URL对象的getPath方法对于包含中文或空格的问题
|
||||
path = URLUtil.toURI(url).getPath();
|
||||
path = toURI(url).getPath();
|
||||
} catch (UtilException e) {
|
||||
// ignore
|
||||
}
|
||||
@ -569,7 +563,7 @@ public class URLUtil {
|
||||
location = encode(location);
|
||||
}
|
||||
try {
|
||||
return new URI(location);
|
||||
return new URI(StrUtil.trim(location));
|
||||
} catch (URISyntaxException e) {
|
||||
throw new UtilException(e);
|
||||
}
|
||||
|
@ -1116,6 +1116,8 @@ public class ZipUtil {
|
||||
* @since 5.0.5
|
||||
*/
|
||||
private static File buildFile(File outFile, String fileName) {
|
||||
// 替换Windows路径分隔符为Linux路径分隔符,便于统一处理
|
||||
fileName = fileName.replace('\\', '/');
|
||||
if (false == FileUtil.isWindows()
|
||||
// 检查文件名中是否包含"/",不考虑以"/"结尾的情况
|
||||
&& fileName.lastIndexOf(CharUtil.SLASH, fileName.length() - 2) > 0) {
|
||||
|
@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class ConvertToNumberTest {
|
||||
@ -31,4 +32,13 @@ public class ConvertToNumberTest {
|
||||
assert date != null;
|
||||
Assert.assertEquals(date.getTime(), dateLong.longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBigDecimalTest(){
|
||||
BigDecimal bigDecimal = Convert.toBigDecimal("1.1f");
|
||||
Assert.assertEquals(1.1f, bigDecimal.floatValue(), 1);
|
||||
|
||||
bigDecimal = Convert.toBigDecimal("1L");
|
||||
Assert.assertEquals(1L, bigDecimal.longValue());
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package cn.hutool.core.date;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.BetweenFormater.Level;
|
||||
import cn.hutool.core.date.format.FastDateFormat;
|
||||
import cn.hutool.core.lang.Console;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -74,4 +74,9 @@ public class NetUtilTest {
|
||||
Assert.assertEquals("/", httpCookie.getPath());
|
||||
Assert.assertEquals("cookiedomain.com", httpCookie.getDomain());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLocalHostNameTest() {
|
||||
Assert.assertNotNull(NetUtil.getLocalHostName());
|
||||
}
|
||||
}
|
||||
|
@ -37,4 +37,11 @@ public class EscapeUtilTest {
|
||||
String unescape = EscapeUtil.unescape(escape);
|
||||
Assert.assertEquals(str, unescape);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void escapeSinleQuotesTest(){
|
||||
String str = "'some text with single quotes'";
|
||||
final String s = EscapeUtil.escapeHtml4(str);
|
||||
Assert.assertEquals(str, s);
|
||||
}
|
||||
}
|
||||
|
@ -1,261 +1,272 @@
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
/**
|
||||
* {@link NumberUtil} 单元测试类
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class NumberUtilTest {
|
||||
|
||||
@Test
|
||||
public void addTest() {
|
||||
Float a = 3.15f;
|
||||
Double b = 4.22;
|
||||
double result = NumberUtil.add(a, b).doubleValue();
|
||||
Assert.assertEquals(7.37, result, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addTest2() {
|
||||
double a = 3.15f;
|
||||
double b = 4.22;
|
||||
double result = NumberUtil.add(a, b);
|
||||
Assert.assertEquals(7.37, result, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addTest3() {
|
||||
float a = 3.15f;
|
||||
double b = 4.22;
|
||||
double result = NumberUtil.add(a, b, a, b).doubleValue();
|
||||
Assert.assertEquals(14.74, result, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addTest4() {
|
||||
BigDecimal result = NumberUtil.add(new BigDecimal("133"), new BigDecimal("331"));
|
||||
Assert.assertEquals(new BigDecimal("464"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isIntegerTest() {
|
||||
Assert.assertTrue(NumberUtil.isInteger("-12"));
|
||||
Assert.assertTrue(NumberUtil.isInteger("256"));
|
||||
Assert.assertTrue(NumberUtil.isInteger("0256"));
|
||||
Assert.assertTrue(NumberUtil.isInteger("0"));
|
||||
Assert.assertFalse(NumberUtil.isInteger("23.4"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLongTest() {
|
||||
Assert.assertTrue(NumberUtil.isLong("-12"));
|
||||
Assert.assertTrue(NumberUtil.isLong("256"));
|
||||
Assert.assertTrue(NumberUtil.isLong("0256"));
|
||||
Assert.assertTrue(NumberUtil.isLong("0"));
|
||||
Assert.assertFalse(NumberUtil.isLong("23.4"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNumberTest() {
|
||||
Assert.assertTrue(NumberUtil.isNumber("28.55"));
|
||||
Assert.assertTrue(NumberUtil.isNumber("0"));
|
||||
Assert.assertTrue(NumberUtil.isNumber("+100.10"));
|
||||
Assert.assertTrue(NumberUtil.isNumber("-22.022"));
|
||||
Assert.assertTrue(NumberUtil.isNumber("0X22"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void divTest() {
|
||||
double result = NumberUtil.div(0, 1);
|
||||
Assert.assertEquals(0.0, result, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundTest() {
|
||||
|
||||
// 四舍
|
||||
String round1 = NumberUtil.roundStr(2.674, 2);
|
||||
String round2 = NumberUtil.roundStr("2.674", 2);
|
||||
Assert.assertEquals("2.67", round1);
|
||||
Assert.assertEquals("2.67", round2);
|
||||
|
||||
// 五入
|
||||
String round3 = NumberUtil.roundStr(2.675, 2);
|
||||
String round4 = NumberUtil.roundStr("2.675", 2);
|
||||
Assert.assertEquals("2.68", round3);
|
||||
Assert.assertEquals("2.68", round4);
|
||||
|
||||
// 四舍六入五成双
|
||||
String round31 = NumberUtil.roundStr(4.245, 2, RoundingMode.HALF_EVEN);
|
||||
String round41 = NumberUtil.roundStr("4.2451", 2, RoundingMode.HALF_EVEN);
|
||||
Assert.assertEquals("4.24", round31);
|
||||
Assert.assertEquals("4.25", round41);
|
||||
|
||||
// 补0
|
||||
String round5 = NumberUtil.roundStr(2.6005, 2);
|
||||
String round6 = NumberUtil.roundStr("2.6005", 2);
|
||||
Assert.assertEquals("2.60", round5);
|
||||
Assert.assertEquals("2.60", round6);
|
||||
|
||||
// 补0
|
||||
String round7 = NumberUtil.roundStr(2.600, 2);
|
||||
String round8 = NumberUtil.roundStr("2.600", 2);
|
||||
Assert.assertEquals("2.60", round7);
|
||||
Assert.assertEquals("2.60", round8);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundStrTest() {
|
||||
String roundStr = NumberUtil.roundStr(2.647, 2);
|
||||
Assert.assertEquals(roundStr, "2.65");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundHalfEvenTest() {
|
||||
String roundStr = NumberUtil.roundHalfEven(4.245, 2).toString();
|
||||
Assert.assertEquals(roundStr, "4.24");
|
||||
roundStr = NumberUtil.roundHalfEven(4.2450, 2).toString();
|
||||
Assert.assertEquals(roundStr, "4.24");
|
||||
roundStr = NumberUtil.roundHalfEven(4.2451, 2).toString();
|
||||
Assert.assertEquals(roundStr, "4.25");
|
||||
roundStr = NumberUtil.roundHalfEven(4.2250, 2).toString();
|
||||
Assert.assertEquals(roundStr, "4.22");
|
||||
|
||||
roundStr = NumberUtil.roundHalfEven(1.2050, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.20");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2150, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.22");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2250, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.22");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2350, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.24");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2450, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.24");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2550, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.26");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2650, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.26");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2750, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.28");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2850, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.28");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2950, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.30");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decimalFormatTest() {
|
||||
long c = 299792458;// 光速
|
||||
|
||||
String format = NumberUtil.decimalFormat(",###", c);
|
||||
Assert.assertEquals("299,792,458", format);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decimalFormatMoneyTest() {
|
||||
double c = 299792400.543534534;
|
||||
|
||||
String format = NumberUtil.decimalFormatMoney(c);
|
||||
Assert.assertEquals("299,792,400.54", format);
|
||||
|
||||
double value = 0.5;
|
||||
String money = NumberUtil.decimalFormatMoney(value);
|
||||
Assert.assertEquals("0.50", money);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsTest() {
|
||||
Assert.assertTrue(NumberUtil.equals(new BigDecimal("0.00"), BigDecimal.ZERO));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatPercentTest() {
|
||||
String str = NumberUtil.formatPercent(0.33543545, 2);
|
||||
Assert.assertEquals("33.54%", str);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBigDecimalTest() {
|
||||
double a = 3.14;
|
||||
|
||||
BigDecimal bigDecimal = NumberUtil.toBigDecimal(a);
|
||||
Assert.assertEquals("3.14", bigDecimal.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maxTest() {
|
||||
int max = NumberUtil.max(5,4,3,6,1);
|
||||
Assert.assertEquals(6, max);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void minTest() {
|
||||
int min = NumberUtil.min(5,4,3,6,1);
|
||||
Assert.assertEquals(1, min);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseIntTest() {
|
||||
int v1 = NumberUtil.parseInt("0xFF");
|
||||
Assert.assertEquals(255, v1);
|
||||
int v2 = NumberUtil.parseInt("010");
|
||||
Assert.assertEquals(10, v2);
|
||||
int v3 = NumberUtil.parseInt("10");
|
||||
Assert.assertEquals(10, v3);
|
||||
int v4 = NumberUtil.parseInt(" ");
|
||||
Assert.assertEquals(0, v4);
|
||||
int v5 = NumberUtil.parseInt("10F");
|
||||
Assert.assertEquals(10, v5);
|
||||
int v6 = NumberUtil.parseInt("22.4D");
|
||||
Assert.assertEquals(22, v6);
|
||||
|
||||
int v7 = NumberUtil.parseInt("0");
|
||||
Assert.assertEquals(0, v7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseLongTest() {
|
||||
long v1 = NumberUtil.parseLong("0xFF");
|
||||
Assert.assertEquals(255L, v1);
|
||||
long v2 = NumberUtil.parseLong("010");
|
||||
Assert.assertEquals(10L, v2);
|
||||
long v3 = NumberUtil.parseLong("10");
|
||||
Assert.assertEquals(10L, v3);
|
||||
long v4 = NumberUtil.parseLong(" ");
|
||||
Assert.assertEquals(0L, v4);
|
||||
long v5 = NumberUtil.parseLong("10F");
|
||||
Assert.assertEquals(10L, v5);
|
||||
long v6 = NumberUtil.parseLong("22.4D");
|
||||
Assert.assertEquals(22L, v6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void factorialTest(){
|
||||
long factorial = NumberUtil.factorial(0);
|
||||
Assert.assertEquals(1, factorial);
|
||||
|
||||
Assert.assertEquals(1L, NumberUtil.factorial(1));
|
||||
Assert.assertEquals(1307674368000L, NumberUtil.factorial(15));
|
||||
Assert.assertEquals(2432902008176640000L, NumberUtil.factorial(20));
|
||||
|
||||
factorial = NumberUtil.factorial(5, 0);
|
||||
Assert.assertEquals(120, factorial);
|
||||
factorial = NumberUtil.factorial(5, 1);
|
||||
Assert.assertEquals(120, factorial);
|
||||
Assert.assertEquals(5, NumberUtil.factorial(5, 4));
|
||||
Assert.assertEquals(2432902008176640000L, NumberUtil.factorial(20, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mulTest(){
|
||||
final BigDecimal mul = NumberUtil.mul(new BigDecimal("10"), null);
|
||||
Assert.assertEquals(BigDecimal.ZERO, mul);
|
||||
}
|
||||
}
|
||||
package cn.hutool.core.util;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
/**
|
||||
* {@link NumberUtil} 单元测试类
|
||||
*
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class NumberUtilTest {
|
||||
|
||||
@Test
|
||||
public void addTest() {
|
||||
Float a = 3.15f;
|
||||
Double b = 4.22;
|
||||
double result = NumberUtil.add(a, b).doubleValue();
|
||||
Assert.assertEquals(7.37, result, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addTest2() {
|
||||
double a = 3.15f;
|
||||
double b = 4.22;
|
||||
double result = NumberUtil.add(a, b);
|
||||
Assert.assertEquals(7.37, result, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addTest3() {
|
||||
float a = 3.15f;
|
||||
double b = 4.22;
|
||||
double result = NumberUtil.add(a, b, a, b).doubleValue();
|
||||
Assert.assertEquals(14.74, result, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addTest4() {
|
||||
BigDecimal result = NumberUtil.add(new BigDecimal("133"), new BigDecimal("331"));
|
||||
Assert.assertEquals(new BigDecimal("464"), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isIntegerTest() {
|
||||
Assert.assertTrue(NumberUtil.isInteger("-12"));
|
||||
Assert.assertTrue(NumberUtil.isInteger("256"));
|
||||
Assert.assertTrue(NumberUtil.isInteger("0256"));
|
||||
Assert.assertTrue(NumberUtil.isInteger("0"));
|
||||
Assert.assertFalse(NumberUtil.isInteger("23.4"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLongTest() {
|
||||
Assert.assertTrue(NumberUtil.isLong("-12"));
|
||||
Assert.assertTrue(NumberUtil.isLong("256"));
|
||||
Assert.assertTrue(NumberUtil.isLong("0256"));
|
||||
Assert.assertTrue(NumberUtil.isLong("0"));
|
||||
Assert.assertFalse(NumberUtil.isLong("23.4"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNumberTest() {
|
||||
Assert.assertTrue(NumberUtil.isNumber("28.55"));
|
||||
Assert.assertTrue(NumberUtil.isNumber("0"));
|
||||
Assert.assertTrue(NumberUtil.isNumber("+100.10"));
|
||||
Assert.assertTrue(NumberUtil.isNumber("-22.022"));
|
||||
Assert.assertTrue(NumberUtil.isNumber("0X22"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void divTest() {
|
||||
double result = NumberUtil.div(0, 1);
|
||||
Assert.assertEquals(0.0, result, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundTest() {
|
||||
|
||||
// 四舍
|
||||
String round1 = NumberUtil.roundStr(2.674, 2);
|
||||
String round2 = NumberUtil.roundStr("2.674", 2);
|
||||
Assert.assertEquals("2.67", round1);
|
||||
Assert.assertEquals("2.67", round2);
|
||||
|
||||
// 五入
|
||||
String round3 = NumberUtil.roundStr(2.675, 2);
|
||||
String round4 = NumberUtil.roundStr("2.675", 2);
|
||||
Assert.assertEquals("2.68", round3);
|
||||
Assert.assertEquals("2.68", round4);
|
||||
|
||||
// 四舍六入五成双
|
||||
String round31 = NumberUtil.roundStr(4.245, 2, RoundingMode.HALF_EVEN);
|
||||
String round41 = NumberUtil.roundStr("4.2451", 2, RoundingMode.HALF_EVEN);
|
||||
Assert.assertEquals("4.24", round31);
|
||||
Assert.assertEquals("4.25", round41);
|
||||
|
||||
// 补0
|
||||
String round5 = NumberUtil.roundStr(2.6005, 2);
|
||||
String round6 = NumberUtil.roundStr("2.6005", 2);
|
||||
Assert.assertEquals("2.60", round5);
|
||||
Assert.assertEquals("2.60", round6);
|
||||
|
||||
// 补0
|
||||
String round7 = NumberUtil.roundStr(2.600, 2);
|
||||
String round8 = NumberUtil.roundStr("2.600", 2);
|
||||
Assert.assertEquals("2.60", round7);
|
||||
Assert.assertEquals("2.60", round8);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundStrTest() {
|
||||
String roundStr = NumberUtil.roundStr(2.647, 2);
|
||||
Assert.assertEquals(roundStr, "2.65");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundHalfEvenTest() {
|
||||
String roundStr = NumberUtil.roundHalfEven(4.245, 2).toString();
|
||||
Assert.assertEquals(roundStr, "4.24");
|
||||
roundStr = NumberUtil.roundHalfEven(4.2450, 2).toString();
|
||||
Assert.assertEquals(roundStr, "4.24");
|
||||
roundStr = NumberUtil.roundHalfEven(4.2451, 2).toString();
|
||||
Assert.assertEquals(roundStr, "4.25");
|
||||
roundStr = NumberUtil.roundHalfEven(4.2250, 2).toString();
|
||||
Assert.assertEquals(roundStr, "4.22");
|
||||
|
||||
roundStr = NumberUtil.roundHalfEven(1.2050, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.20");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2150, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.22");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2250, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.22");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2350, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.24");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2450, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.24");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2550, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.26");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2650, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.26");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2750, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.28");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2850, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.28");
|
||||
roundStr = NumberUtil.roundHalfEven(1.2950, 2).toString();
|
||||
Assert.assertEquals(roundStr, "1.30");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decimalFormatTest() {
|
||||
long c = 299792458;// 光速
|
||||
|
||||
String format = NumberUtil.decimalFormat(",###", c);
|
||||
Assert.assertEquals("299,792,458", format);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decimalFormatMoneyTest() {
|
||||
double c = 299792400.543534534;
|
||||
|
||||
String format = NumberUtil.decimalFormatMoney(c);
|
||||
Assert.assertEquals("299,792,400.54", format);
|
||||
|
||||
double value = 0.5;
|
||||
String money = NumberUtil.decimalFormatMoney(value);
|
||||
Assert.assertEquals("0.50", money);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsTest() {
|
||||
Assert.assertTrue(NumberUtil.equals(new BigDecimal("0.00"), BigDecimal.ZERO));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatPercentTest() {
|
||||
String str = NumberUtil.formatPercent(0.33543545, 2);
|
||||
Assert.assertEquals("33.54%", str);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toBigDecimalTest() {
|
||||
double a = 3.14;
|
||||
|
||||
BigDecimal bigDecimal = NumberUtil.toBigDecimal(a);
|
||||
Assert.assertEquals("3.14", bigDecimal.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maxTest() {
|
||||
int max = NumberUtil.max(5,4,3,6,1);
|
||||
Assert.assertEquals(6, max);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void minTest() {
|
||||
int min = NumberUtil.min(5,4,3,6,1);
|
||||
Assert.assertEquals(1, min);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseIntTest() {
|
||||
int v1 = NumberUtil.parseInt("0xFF");
|
||||
Assert.assertEquals(255, v1);
|
||||
int v2 = NumberUtil.parseInt("010");
|
||||
Assert.assertEquals(10, v2);
|
||||
int v3 = NumberUtil.parseInt("10");
|
||||
Assert.assertEquals(10, v3);
|
||||
int v4 = NumberUtil.parseInt(" ");
|
||||
Assert.assertEquals(0, v4);
|
||||
int v5 = NumberUtil.parseInt("10F");
|
||||
Assert.assertEquals(10, v5);
|
||||
int v6 = NumberUtil.parseInt("22.4D");
|
||||
Assert.assertEquals(22, v6);
|
||||
|
||||
int v7 = NumberUtil.parseInt("0");
|
||||
Assert.assertEquals(0, v7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseLongTest() {
|
||||
long v1 = NumberUtil.parseLong("0xFF");
|
||||
Assert.assertEquals(255L, v1);
|
||||
long v2 = NumberUtil.parseLong("010");
|
||||
Assert.assertEquals(10L, v2);
|
||||
long v3 = NumberUtil.parseLong("10");
|
||||
Assert.assertEquals(10L, v3);
|
||||
long v4 = NumberUtil.parseLong(" ");
|
||||
Assert.assertEquals(0L, v4);
|
||||
long v5 = NumberUtil.parseLong("10F");
|
||||
Assert.assertEquals(10L, v5);
|
||||
long v6 = NumberUtil.parseLong("22.4D");
|
||||
Assert.assertEquals(22L, v6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void factorialTest(){
|
||||
long factorial = NumberUtil.factorial(0);
|
||||
Assert.assertEquals(1, factorial);
|
||||
|
||||
Assert.assertEquals(1L, NumberUtil.factorial(1));
|
||||
Assert.assertEquals(1307674368000L, NumberUtil.factorial(15));
|
||||
Assert.assertEquals(2432902008176640000L, NumberUtil.factorial(20));
|
||||
|
||||
factorial = NumberUtil.factorial(5, 0);
|
||||
Assert.assertEquals(120, factorial);
|
||||
factorial = NumberUtil.factorial(5, 1);
|
||||
Assert.assertEquals(120, factorial);
|
||||
|
||||
Assert.assertEquals(5, NumberUtil.factorial(5, 4));
|
||||
Assert.assertEquals(2432902008176640000L, NumberUtil.factorial(20, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mulTest(){
|
||||
final BigDecimal mul = NumberUtil.mul(new BigDecimal("10"), null);
|
||||
Assert.assertEquals(BigDecimal.ZERO, mul);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void isPowerOfTwoTest() {
|
||||
Assert.assertEquals(false, NumberUtil.isPowerOfTwo(-1));
|
||||
Assert.assertEquals(true, NumberUtil.isPowerOfTwo(16));
|
||||
Assert.assertEquals(true, NumberUtil.isPowerOfTwo(65536));
|
||||
Assert.assertEquals(true, NumberUtil.isPowerOfTwo(1));
|
||||
Assert.assertEquals(false, NumberUtil.isPowerOfTwo(17));
|
||||
}
|
||||
}
|
||||
|
@ -84,4 +84,11 @@ public class URLUtilTest {
|
||||
String encode2 = URLUtil.encodeQuery(body);
|
||||
Assert.assertEquals("366466+-+%E5%89%AF%E6%9C%AC.jpg", encode2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPathTest(){
|
||||
String url = " http://www.aaa.bbb/search?scope=ccc&q=ddd";
|
||||
String path = URLUtil.getPath(url);
|
||||
Assert.assertEquals("/search", path);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-cron</artifactId>
|
||||
|
@ -1,12 +1,12 @@
|
||||
package cn.hutool.cron.listener;
|
||||
|
||||
import cn.hutool.cron.TaskExecutor;
|
||||
import cn.hutool.log.StaticLog;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import cn.hutool.cron.TaskExecutor;
|
||||
import cn.hutool.log.StaticLog;
|
||||
|
||||
/**
|
||||
* 监听调度器,统一管理监听
|
||||
* @author Looly
|
||||
@ -49,9 +49,9 @@ public class TaskListenerManager implements Serializable {
|
||||
synchronized (listeners) {
|
||||
int size = listeners.size();
|
||||
TaskListener listener;
|
||||
for (int i = 0; i < size; i++) {
|
||||
listener = listeners.get(i);
|
||||
if(null != listener){
|
||||
for (TaskListener taskListener : listeners) {
|
||||
listener = taskListener;
|
||||
if (null != listener) {
|
||||
listener.onStart(executor);
|
||||
}
|
||||
}
|
||||
@ -65,8 +65,7 @@ public class TaskListenerManager implements Serializable {
|
||||
public void notifyTaskSucceeded(TaskExecutor executor) {
|
||||
synchronized (listeners) {
|
||||
int size = listeners.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
TaskListener listenerl = listeners.get(i);
|
||||
for (TaskListener listenerl : listeners) {
|
||||
listenerl.onSucceeded(executor);
|
||||
}
|
||||
}
|
||||
@ -82,8 +81,7 @@ public class TaskListenerManager implements Serializable {
|
||||
synchronized (listeners) {
|
||||
int size = listeners.size();
|
||||
if(size > 0){
|
||||
for (int i = 0; i < size; i++) {
|
||||
TaskListener listenerl = listeners.get(i);
|
||||
for (TaskListener listenerl : listeners) {
|
||||
listenerl.onFailed(executor, exception);
|
||||
}
|
||||
}else{
|
||||
|
@ -1,12 +1,13 @@
|
||||
package cn.hutool.cron.demo;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import cn.hutool.core.lang.Console;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.cron.CronUtil;
|
||||
import cn.hutool.cron.TaskExecutor;
|
||||
import cn.hutool.cron.listener.TaskListener;
|
||||
import cn.hutool.cron.task.Task;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* 定时任务样例
|
||||
@ -38,6 +39,23 @@ public class CronTest {
|
||||
@Test
|
||||
@Ignore
|
||||
public void cronTest2() {
|
||||
CronUtil.getScheduler().addListener(new TaskListener() {
|
||||
@Override
|
||||
public void onStart(TaskExecutor executor) {
|
||||
Console.log("Listen task start!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSucceeded(TaskExecutor executor) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed(TaskExecutor executor, Throwable exception) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// 支持秒级别定时任务
|
||||
CronUtil.setMatchSecond(true);
|
||||
CronUtil.start();
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
|
@ -499,8 +499,10 @@ public class SM2 extends AbstractAsymmetricCrypto<SM2> {
|
||||
*/
|
||||
private SM2Engine getEngine() {
|
||||
if (null == this.engine) {
|
||||
Assert.notNull(this.digest, "digest must be not null !");
|
||||
this.engine = new SM2Engine(this.digest, this.mode);
|
||||
}
|
||||
this.digest.reset();
|
||||
return this.engine;
|
||||
}
|
||||
|
||||
@ -511,8 +513,10 @@ public class SM2 extends AbstractAsymmetricCrypto<SM2> {
|
||||
*/
|
||||
private SM2Signer getSigner() {
|
||||
if (null == this.signer) {
|
||||
Assert.notNull(this.digest, "digest must be not null !");
|
||||
this.signer = new SM2Signer(this.encoding, this.digest);
|
||||
}
|
||||
this.digest.reset();
|
||||
return this.signer;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------------------------------- Private method end
|
||||
|
@ -1,16 +1,17 @@
|
||||
package cn.hutool.crypto.symmetric;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.CryptoException;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
|
||||
/**
|
||||
* RC4加密解密算法实现<br>
|
||||
@ -97,6 +98,17 @@ public class RC4 implements Serializable {
|
||||
return HexUtil.encodeHexStr(encrypt(data, charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密,使用UTF-8编码
|
||||
*
|
||||
* @param data 被加密的字符串
|
||||
* @return 加密后的Hex
|
||||
* @since 5.4.4
|
||||
*/
|
||||
public String encryptHex(String data) {
|
||||
return HexUtil.encodeHexStr(encrypt(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密
|
||||
*
|
||||
@ -109,6 +121,18 @@ public class RC4 implements Serializable {
|
||||
return Base64.encode(encrypt(data, charset));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加密,使用UTF-8编码
|
||||
*
|
||||
* @param data 被加密的字符串
|
||||
* @return 加密后的Base64
|
||||
* @since 5.4.4
|
||||
*/
|
||||
public String encryptBase64(String data) {
|
||||
return Base64.encode(encrypt(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
*
|
||||
@ -132,6 +156,30 @@ public class RC4 implements Serializable {
|
||||
return decrypt(message, CharsetUtil.CHARSET_UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密Hex(16进制)或Base64表示的字符串,使用默认编码UTF-8
|
||||
*
|
||||
* @param message 消息
|
||||
* @return 明文
|
||||
* @since 5.4.4
|
||||
*/
|
||||
public String decrypt(String message) {
|
||||
return decrypt(SecureUtil.decode(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密Hex(16进制)或Base64表示的字符串
|
||||
*
|
||||
* @param message 明文
|
||||
* @param charset 解密后的charset
|
||||
* @return 明文
|
||||
* @since 5.4.4
|
||||
*/
|
||||
public String decrypt(String message, Charset charset) {
|
||||
return StrUtil.str(decrypt(message), charset);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加密或解密指定值,调用此方法前需初始化密钥
|
||||
*
|
||||
@ -216,4 +264,4 @@ public class RC4 implements Serializable {
|
||||
sbox[j] = temp;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------- Private method end
|
||||
}
|
||||
}
|
||||
|
@ -229,4 +229,18 @@ public class SM2Test {
|
||||
Assert.assertEquals(data, decryptStr);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encryptAndSignTest(){
|
||||
SM2 sm2 = SmUtil.sm2();
|
||||
|
||||
String src = "Sm2Test";
|
||||
byte[] data = sm2.encrypt(src, KeyType.PublicKey);
|
||||
byte[] sign = sm2.sign(src.getBytes());
|
||||
|
||||
Assert.assertTrue(sm2.verify( src.getBytes(), sign));
|
||||
|
||||
byte[] dec = sm2.decrypt(data, KeyType.PrivateKey);
|
||||
Assert.assertArrayEquals(dec, src.getBytes());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.hutool.crypto.test.symmetric;
|
||||
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -36,4 +37,35 @@ public class RC4Test {
|
||||
String msg2 = rc4.decrypt(crypt2);
|
||||
Assert.assertEquals(message2, msg2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecryptWithHexMessage() {
|
||||
String message = "这是第一个用来测试密文为十六进制字符串的消息!";
|
||||
String key = "生成一个密钥";
|
||||
RC4 rc4 = new RC4(key);
|
||||
String encryptHex = rc4.encryptHex(message, CharsetUtil.CHARSET_UTF_8);
|
||||
String msg = rc4.decrypt(encryptHex);
|
||||
Assert.assertEquals(message, msg);
|
||||
|
||||
String message2 = "这是第二个用来测试密文为十六进制字符串的消息!";
|
||||
String encryptHex2 = rc4.encryptHex(message2);
|
||||
String msg2 = rc4.decrypt(encryptHex2);
|
||||
Assert.assertEquals(message2, msg2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDecryptWithBase64Message() {
|
||||
String message = "这是第一个用来测试密文为Base64编码的消息!";
|
||||
String key = "生成一个密钥";
|
||||
RC4 rc4 = new RC4(key);
|
||||
String encryptHex = rc4.encryptBase64(message, CharsetUtil.CHARSET_UTF_8);
|
||||
String msg = rc4.decrypt(encryptHex);
|
||||
Assert.assertEquals(message, msg);
|
||||
|
||||
String message2 = "这是第一个用来测试密文为Base64编码的消息!";
|
||||
String encryptHex2 = rc4.encryptBase64(message2);
|
||||
String msg2 = rc4.decrypt(encryptHex2);
|
||||
Assert.assertEquals(message2, msg2);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-db</artifactId>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-dfa</artifactId>
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.hutool.dfa;
|
||||
|
||||
import cn.hutool.core.lang.Filter;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
@ -13,8 +14,7 @@ import java.util.List;
|
||||
*
|
||||
*/
|
||||
public final class SensitiveUtil {
|
||||
// private static final Log log = LogFactory.get();
|
||||
|
||||
|
||||
public static final char DEFAULT_SEPARATOR = StrUtil.C_COMMA;
|
||||
private static final WordTree sensitiveTree = new WordTree();
|
||||
|
||||
@ -72,6 +72,19 @@ public final class SensitiveUtil {
|
||||
init(sensitiveWords, DEFAULT_SEPARATOR, isAsync);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置字符过滤规则,通过定义字符串过滤规则,过滤不需要的字符<br>
|
||||
* 当accept为false时,此字符不参与匹配
|
||||
*
|
||||
* @param charFilter 过滤函数
|
||||
* @since 5.4.4
|
||||
*/
|
||||
public static void setCharFilter(Filter<Character> charFilter) {
|
||||
if(charFilter != null) {
|
||||
sensitiveTree.setCharFilter(charFilter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否包含敏感词
|
||||
* @param text 文本
|
||||
|
@ -11,7 +11,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
*/
|
||||
public class StopChar {
|
||||
/** 不需要处理的词,如标点符号、空格等 */
|
||||
public static final Set<Character> STOP_WORD = CollUtil.newHashSet(new Character[] { ' ', '\'', '、', '。', //
|
||||
public static final Set<Character> STOP_WORD = CollUtil.newHashSet(' ', '\'', '、', '。', //
|
||||
'·', 'ˉ', 'ˇ', '々', '—', '~', '‖', '…', '‘', '’', '“', '”', '〔', '〕', '〈', '〉', '《', '》', '「', '」', '『', //
|
||||
'』', '〖', '〗', '【', '】', '±', '+', '-', '×', '÷', '∧', '∨', '∑', '∏', '∪', '∩', '∈', '√', '⊥', '⊙', '∫', //
|
||||
'∮', '≡', '≌', '≈', '∽', '∝', '≠', '≮', '≯', '≤', '≥', '∞', '∶', '∵', '∴', '∷', '♂', '♀', '°', '′', '〃', //
|
||||
@ -26,7 +26,8 @@ public class StopChar {
|
||||
'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', 'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π', //
|
||||
'ρ', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω', '(', ')', '〔', '〕', '^', '﹊', '﹍', '╭', '╮', '╰', '╯', '', '_', //
|
||||
'', '^', '(', '^', ':', '!', '/', '\\', '\"', '<', '>', '`', '·', '。', '{', '}', '~', '~', '(', ')', '-', //
|
||||
'√', '$', '@', '*', '&', '#', '卐', '㎎', '㎏', '㎜', '㎝', '㎞', '㎡', '㏄', '㏎', '㏑', '㏒', '㏕' });
|
||||
'√', '$', '@', '*', '&', '#', '卐', '㎎', '㎏', '㎜', '㎝', '㎞', '㎡', '㏄', '㏎', '㏑', '㏒', '㏕', '+', '=', '?',
|
||||
':', '.', '!', ';', ']','|','%');
|
||||
|
||||
/**
|
||||
* 判断指定的词是否是不处理的词。 如果参数为空,则返回true,因为空也属于不处理的字符。
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-extra</artifactId>
|
||||
|
@ -1,15 +1,13 @@
|
||||
package cn.hutool.extra.emoji;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.vdurmont.emoji.Emoji;
|
||||
import com.vdurmont.emoji.EmojiManager;
|
||||
import com.vdurmont.emoji.EmojiParser;
|
||||
import com.vdurmont.emoji.EmojiTrie;
|
||||
import com.vdurmont.emoji.EmojiParser.FitzpatrickAction;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 基于https://github.com/vdurmont/emoji-java的Emoji表情工具类
|
||||
* <p>
|
||||
@ -38,22 +36,7 @@ public class EmojiUtil {
|
||||
* @since 4.5.11
|
||||
*/
|
||||
public static boolean containsEmoji(String str) {
|
||||
if (str == null) {
|
||||
return false;
|
||||
}
|
||||
final char[] chars = str.toCharArray();
|
||||
EmojiTrie.Matches status;
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
for (int j = i + 1; j <= chars.length; j++) {
|
||||
status = EmojiManager.isEmoji(Arrays.copyOfRange(chars, i, j));
|
||||
if (status.impossibleMatch()) {
|
||||
break;
|
||||
} else if (status.exactMatch()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return EmojiManager.containsEmoji(str);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -342,6 +342,20 @@ public class Ftp extends AbstractFtp {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务端目录状态。
|
||||
* @param path 路径
|
||||
* @return 状态int,服务端不同,返回不同
|
||||
* @since 5.4.3
|
||||
*/
|
||||
public int stat(String path) {
|
||||
try {
|
||||
return this.client.stat(path);
|
||||
} catch (IOException e) {
|
||||
throw new FtpException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断ftp服务器文件是否存在
|
||||
*
|
||||
|
@ -3,7 +3,7 @@ package cn.hutool.extra.mail;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
|
||||
/**
|
||||
* 全局邮件帐户,依赖于邮件配置文件{@link MailAccount#MAIL_SETTING_PATH}或{@link MailAccount#MAIL_SETTING_PATH2}
|
||||
* 全局邮件帐户,依赖于邮件配置文件{@link MailAccount#MAIL_SETTING_PATHS}
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
@ -35,31 +35,13 @@ public enum GlobalMailAccount {
|
||||
* @return MailAccount
|
||||
*/
|
||||
private MailAccount createDefaultAccount() {
|
||||
MailAccount mailAccount = null;
|
||||
try {
|
||||
mailAccount = new MailAccount(MailAccount.MAIL_SETTING_PATH);
|
||||
} catch (IORuntimeException e) {
|
||||
//ignore
|
||||
}
|
||||
|
||||
// 寻找config/mailAccount.setting
|
||||
if(null == mailAccount) {
|
||||
for (String mailSettingPath : MailAccount.MAIL_SETTING_PATHS) {
|
||||
try {
|
||||
mailAccount = new MailAccount(MailAccount.MAIL_SETTING_PATH2);
|
||||
} catch (IORuntimeException e) {
|
||||
return new MailAccount(mailSettingPath);
|
||||
} catch (IORuntimeException ignore) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
// 寻找mail.setting
|
||||
if(null == mailAccount) {
|
||||
try {
|
||||
mailAccount = new MailAccount(MailAccount.MAIL_SETTING_PATH3);
|
||||
} catch (IORuntimeException e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
return mailAccount;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +32,7 @@ public class MailAccount implements Serializable {
|
||||
private static final String MAIL_DEBUG = "mail.debug";
|
||||
private static final String SPLIT_LONG_PARAMS = "mail.mime.splitlongparameters";
|
||||
|
||||
public static final String MAIL_SETTING_PATH = "config/mail.setting";
|
||||
public static final String MAIL_SETTING_PATH2 = "config/mailAccount.setting";
|
||||
public static final String MAIL_SETTING_PATH3 = "mail.setting";
|
||||
public static final String[] MAIL_SETTING_PATHS = new String[]{"config/mail.setting", "config/mailAccount.setting", "mail.setting"};
|
||||
|
||||
/**
|
||||
* SMTP服务器域名
|
||||
|
@ -16,4 +16,13 @@ public class EmojiUtilTest {
|
||||
String alias = EmojiUtil.toAlias("😄");
|
||||
Assert.assertEquals(":smile:", alias);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void containsEmojiTest() {
|
||||
boolean containsEmoji = EmojiUtil.containsEmoji("测试一下是否包含EMOJ:😄");
|
||||
Assert.assertEquals(containsEmoji, true);
|
||||
boolean notContainsEmoji = EmojiUtil.containsEmoji("不包含EMOJ:^_^");
|
||||
Assert.assertEquals(notContainsEmoji, false);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-http</artifactId>
|
||||
|
@ -19,7 +19,6 @@ import javax.xml.soap.Name;
|
||||
import javax.xml.soap.SOAPBodyElement;
|
||||
import javax.xml.soap.SOAPElement;
|
||||
import javax.xml.soap.SOAPException;
|
||||
import javax.xml.soap.SOAPHeader;
|
||||
import javax.xml.soap.SOAPHeaderElement;
|
||||
import javax.xml.soap.SOAPMessage;
|
||||
import java.io.IOException;
|
||||
@ -93,7 +92,7 @@ public class SoapClient extends HttpBase<SoapClient> {
|
||||
* 创建SOAP客户端,默认使用soap1.1版本协议
|
||||
*
|
||||
* @param url WS的URL地址
|
||||
* @return {@link SoapClient}
|
||||
* @return this
|
||||
*/
|
||||
public static SoapClient create(String url) {
|
||||
return new SoapClient(url);
|
||||
@ -104,7 +103,7 @@ public class SoapClient extends HttpBase<SoapClient> {
|
||||
*
|
||||
* @param url WS的URL地址
|
||||
* @param protocol 协议,见{@link SoapProtocol}
|
||||
* @return {@link SoapClient}
|
||||
* @return this
|
||||
*/
|
||||
public static SoapClient create(String url, SoapProtocol protocol) {
|
||||
return new SoapClient(url, protocol);
|
||||
@ -116,7 +115,7 @@ public class SoapClient extends HttpBase<SoapClient> {
|
||||
* @param url WS的URL地址
|
||||
* @param protocol 协议,见{@link SoapProtocol}
|
||||
* @param namespaceURI 方法上的命名空间URI
|
||||
* @return {@link SoapClient}
|
||||
* @return this
|
||||
* @since 4.5.6
|
||||
*/
|
||||
public static SoapClient create(String url, SoapProtocol protocol, String namespaceURI) {
|
||||
@ -235,7 +234,7 @@ public class SoapClient extends HttpBase<SoapClient> {
|
||||
*
|
||||
* @param name 头信息标签名
|
||||
* @return this
|
||||
* @deprecated 为了和Http Hrader区分,请使用{@link #setSOAPHeader(QName)}
|
||||
* @deprecated 为了和Http Hrader区分,请使用{@link #addSOAPHeader(QName)}
|
||||
*/
|
||||
@Deprecated
|
||||
public SoapClient setHeader(QName name) {
|
||||
@ -247,9 +246,12 @@ public class SoapClient extends HttpBase<SoapClient> {
|
||||
*
|
||||
* @param name 头信息标签名
|
||||
* @return this
|
||||
* @deprecated 为了便于设置子节点或者value值,请使用{@link #addSOAPHeader(QName)}
|
||||
*/
|
||||
@Deprecated
|
||||
public SoapClient setSOAPHeader(QName name) {
|
||||
return setSOAPHeader(name, null, null, null, null);
|
||||
addSOAPHeader(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -261,7 +263,7 @@ public class SoapClient extends HttpBase<SoapClient> {
|
||||
* @param mustUnderstand 标题项对于要对其进行处理的接收者来说是强制的还是可选的
|
||||
* @param relay relay属性
|
||||
* @return this
|
||||
* @deprecated 为了和Http Hrader区分,请使用{@link #setSOAPHeader(QName, String, String, Boolean, Boolean)}
|
||||
* @deprecated 为了和Http Header区分,请使用{@link #addSOAPHeader(QName, String, String, Boolean, Boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public SoapClient setHeader(QName name, String actorURI, String roleUri, Boolean mustUnderstand, Boolean relay) {
|
||||
@ -277,13 +279,29 @@ public class SoapClient extends HttpBase<SoapClient> {
|
||||
* @param mustUnderstand 标题项对于要对其进行处理的接收者来说是强制的还是可选的
|
||||
* @param relay relay属性
|
||||
* @return this
|
||||
* @deprecated 为了便于设置子节点或者value值,请使用{@link #addSOAPHeader(QName, String, String, Boolean, Boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public SoapClient setSOAPHeader(QName name, String actorURI, String roleUri, Boolean mustUnderstand, Boolean relay) {
|
||||
SOAPHeader header;
|
||||
SOAPHeaderElement ele;
|
||||
addSOAPHeader(name, actorURI, roleUri, mustUnderstand, relay);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加SOAP头信息,方法返回{@link SOAPHeaderElement}可以设置具体属性和子节点
|
||||
*
|
||||
* @param name 头信息标签名
|
||||
* @param actorURI 中间的消息接收者
|
||||
* @param roleUri Role的URI
|
||||
* @param mustUnderstand 标题项对于要对其进行处理的接收者来说是强制的还是可选的
|
||||
* @param relay relay属性
|
||||
* @return {@link SOAPHeaderElement}
|
||||
* @since 5.4.4
|
||||
*/
|
||||
public SOAPHeaderElement addSOAPHeader(QName name, String actorURI, String roleUri, Boolean mustUnderstand, Boolean relay) {
|
||||
final SOAPHeaderElement ele = addSOAPHeader(name);
|
||||
try {
|
||||
header = this.message.getSOAPHeader();
|
||||
ele = header.addHeaderElement(name);
|
||||
if (StrUtil.isNotBlank(roleUri)) {
|
||||
ele.setRole(roleUri);
|
||||
}
|
||||
@ -301,7 +319,24 @@ public class SoapClient extends HttpBase<SoapClient> {
|
||||
ele.setMustUnderstand(mustUnderstand);
|
||||
}
|
||||
|
||||
return this;
|
||||
return ele;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加SOAP头信息,方法返回{@link SOAPHeaderElement}可以设置具体属性和子节点
|
||||
*
|
||||
* @param name 头节点名称
|
||||
* @return {@link SOAPHeaderElement}
|
||||
* @since 5.4.4
|
||||
*/
|
||||
public SOAPHeaderElement addSOAPHeader(QName name){
|
||||
SOAPHeaderElement ele;
|
||||
try {
|
||||
ele = this.message.getSOAPHeader().addHeaderElement(name);
|
||||
} catch (SOAPException e) {
|
||||
throw new SoapRuntimeException(e);
|
||||
}
|
||||
return ele;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,6 +119,7 @@ public class HtmlUtilTest {
|
||||
Assert.assertEquals("<html><body>123'123'</body></html>", escape);
|
||||
String restoreEscaped = HtmlUtil.unescape(escape);
|
||||
Assert.assertEquals(html, restoreEscaped);
|
||||
Assert.assertEquals("'", HtmlUtil.unescape("'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-json</artifactId>
|
||||
|
96
hutool-json/src/test/java/cn/hutool/json/Issue1101Test.java
Normal file
96
hutool-json/src/test/java/cn/hutool/json/Issue1101Test.java
Normal file
@ -0,0 +1,96 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import lombok.Data;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* 测试转换为TreeSet是否成功。 TreeSet必须有默认的比较器
|
||||
*/
|
||||
public class Issue1101Test {
|
||||
|
||||
@Test
|
||||
public void treeMapConvertTest(){
|
||||
String json = "[{\"nodeName\":\"admin\",\"treeNodeId\":\"00010001_52c95b83-2083-4138-99fb-e6e21f0c1277\",\"sort\":0,\"type\":10,\"parentId\":\"00010001\",\"children\":[],\"id\":\"52c95b83-2083-4138-99fb-e6e21f0c1277\",\"status\":true},{\"nodeName\":\"test\",\"treeNodeId\":\"00010001_97054a82-f8ff-46a1-b76c-cbacf6d18045\",\"sort\":0,\"type\":10,\"parentId\":\"00010001\",\"children\":[],\"id\":\"97054a82-f8ff-46a1-b76c-cbacf6d18045\",\"status\":true}]";
|
||||
final JSONArray objects = JSONUtil.parseArray(json);
|
||||
final TreeSet<TreeNodeDto> convert = Convert.convert(new TypeReference<TreeSet<TreeNodeDto>>() {
|
||||
}, objects);
|
||||
Assert.assertEquals(2, convert.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
String json = "{\n" +
|
||||
"\t\"children\": [{\n" +
|
||||
"\t\t\"children\": [],\n" +
|
||||
"\t\t\"id\": \"52c95b83-2083-4138-99fb-e6e21f0c1277\",\n" +
|
||||
"\t\t\"nodeName\": \"admin\",\n" +
|
||||
"\t\t\"parentId\": \"00010001\",\n" +
|
||||
"\t\t\"sort\": 0,\n" +
|
||||
"\t\t\"status\": true,\n" +
|
||||
"\t\t\"treeNodeId\": \"00010001_52c95b83-2083-4138-99fb-e6e21f0c1277\",\n" +
|
||||
"\t\t\"type\": 10\n" +
|
||||
"\t}, {\n" +
|
||||
"\t\t\"children\": [],\n" +
|
||||
"\t\t\"id\": \"97054a82-f8ff-46a1-b76c-cbacf6d18045\",\n" +
|
||||
"\t\t\"nodeName\": \"test\",\n" +
|
||||
"\t\t\"parentId\": \"00010001\",\n" +
|
||||
"\t\t\"sort\": 0,\n" +
|
||||
"\t\t\"status\": true,\n" +
|
||||
"\t\t\"treeNodeId\": \"00010001_97054a82-f8ff-46a1-b76c-cbacf6d18045\",\n" +
|
||||
"\t\t\"type\": 10\n" +
|
||||
"\t}],\n" +
|
||||
"\t\"id\": \"00010001\",\n" +
|
||||
"\t\"nodeName\": \"测试\",\n" +
|
||||
"\t\"parentId\": \"0001\",\n" +
|
||||
"\t\"sort\": 0,\n" +
|
||||
"\t\"status\": true,\n" +
|
||||
"\t\"treeNodeId\": \"00010001\",\n" +
|
||||
"\t\"type\": 0\n" +
|
||||
"}";
|
||||
|
||||
final JSONObject jsonObject = JSONUtil.parseObj(json);
|
||||
|
||||
final TreeNode treeNode = JSONUtil.toBean(jsonObject, TreeNode.class);
|
||||
Assert.assertEquals(2, treeNode.getChildren().size());
|
||||
|
||||
TreeNodeDto dto = new TreeNodeDto();
|
||||
BeanUtil.copyProperties(treeNode, dto, true);
|
||||
Assert.assertEquals(2, dto.getChildren().size());
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class TreeNodeDto {
|
||||
private String id;
|
||||
private String parentId;
|
||||
private int sort;
|
||||
private String nodeName;
|
||||
private int type;
|
||||
private Boolean status;
|
||||
private String treeNodeId;
|
||||
private TreeSet<TreeNodeDto> children = new TreeSet<>(Comparator.comparing(o -> o.id));
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class TreeNode implements Comparable<TreeNode> {
|
||||
private String id;
|
||||
private String parentId;
|
||||
private int sort;
|
||||
private String nodeName;
|
||||
private int type;
|
||||
private Boolean status;
|
||||
private String treeNodeId;
|
||||
private TreeSet<TreeNode> children = new TreeSet<>();
|
||||
|
||||
@Override
|
||||
public int compareTo(TreeNode o) {
|
||||
return id.compareTo(o.getId());
|
||||
}
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.3</version>
|
||||
<version>5.4.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-log</artifactId>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user