C_TIME_ZONE_DISPLAY_CACHE = new ConcurrentHashMap<>(7);
/**
*
@@ -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;
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/format/FormatCache.java b/hutool-core/src/main/java/cn/hutool/core/date/format/FormatCache.java
index 456a4c170..a3491393d 100644
--- a/hutool-core/src/main/java/cn/hutool/core/date/format/FormatCache.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/format/FormatCache.java
@@ -26,7 +26,7 @@ abstract class FormatCache {
private final ConcurrentMap cInstanceCache = new ConcurrentHashMap<>(7);
- private static final ConcurrentMap cDateTimeInstanceCache = new ConcurrentHashMap<>(7);
+ private static final ConcurrentMap C_DATE_TIME_INSTANCE_CACHE = new ConcurrentHashMap<>(7);
/**
* 使用默认的pattern、timezone和locale获得缓存中的实例
@@ -163,7 +163,7 @@ abstract class FormatCache {
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 {
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
diff --git a/hutool-core/src/main/java/cn/hutool/core/img/gif/GifDecoder.java b/hutool-core/src/main/java/cn/hutool/core/img/gif/GifDecoder.java
index 97353f787..0c1dd00b5 100644
--- a/hutool-core/src/main/java/cn/hutool/core/img/gif/GifDecoder.java
+++ b/hutool-core/src/main/java/cn/hutool/core/img/gif/GifDecoder.java
@@ -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
diff --git a/hutool-core/src/main/java/cn/hutool/core/img/gif/NeuQuant.java b/hutool-core/src/main/java/cn/hutool/core/img/gif/NeuQuant.java
index f80f9cbd9..fb152c7c5 100644
--- a/hutool-core/src/main/java/cn/hutool/core/img/gif/NeuQuant.java
+++ b/hutool-core/src/main/java/cn/hutool/core/img/gif/NeuQuant.java
@@ -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);
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java
index aa6884948..5b34d4a25 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java
@@ -20,60 +20,60 @@ import cn.hutool.core.util.StrUtil;
*/
public class FileTypeUtil {
- private static final Map fileTypeMap;
+ private static final Map 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 文件类型,未找到为null
*/
public static String getType(String fileStreamHexHead) {
- for (Entry fileTypeEntry : fileTypeMap.entrySet()) {
+ for (Entry fileTypeEntry : FILE_TYPE_MAP.entrySet()) {
if (StrUtil.startWithIgnoreCase(fileStreamHexHead, fileTypeEntry.getKey())) {
return fileTypeEntry.getValue();
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java
index 6700bb29b..134f377fa 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java
@@ -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();
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Ansi.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Ansi.java
index 662a8759d..44830d137 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Ansi.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Ansi.java
@@ -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;
}
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16CCITT.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16CCITT.java
index 7811855e3..2279fdc37 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16CCITT.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16CCITT.java
@@ -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;
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16CCITTFalse.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16CCITTFalse.java
index 2e8c56b62..bdfd203ff 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16CCITTFalse.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16CCITTFalse.java
@@ -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;
}
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16DNP.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16DNP.java
index fe89a00f0..c03649791 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16DNP.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16DNP.java
@@ -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;
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16IBM.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16IBM.java
index 1c340d29f..fdc793bca 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16IBM.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16IBM.java
@@ -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;
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Maxim.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Maxim.java
index 195bd55bf..38f916cd8 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Maxim.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Maxim.java
@@ -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;
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Modbus.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Modbus.java
index 857f3bf16..4d4ee64a5 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Modbus.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16Modbus.java
@@ -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;
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16USB.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16USB.java
index b9f9503c5..143e7aba0 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16USB.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16USB.java
@@ -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;
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16X25.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16X25.java
index 5c938852d..140e6ab15 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16X25.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16X25.java
@@ -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;
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16XModem.java b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16XModem.java
index 86689e6c9..27d8c5235 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16XModem.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/checksum/crc16/CRC16XModem.java
@@ -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;
}
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTableUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTableUtil.java
new file mode 100644
index 000000000..f894dbf50
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTableUtil.java
@@ -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> HEADER_LIST = new ArrayList<>();
+ /**
+ * 表格体信息
+ */
+ private final List> BODY_LIST = new ArrayList<>();
+ /**
+ * 每列最大字符个数
+ */
+ private List 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 l = new ArrayList<>();
+ HEADER_LIST.add(l);
+ fillColumns(l, titles);
+ return this;
+ }
+
+ /**
+ * 添加体信息
+ *
+ * @param values 列值
+ * @return 自身对象
+ */
+ public ConsoleTableUtil addBody(String... values) {
+ List l = new ArrayList<>();
+ BODY_LIST.add(l);
+ fillColumns(l, values);
+ return this;
+ }
+
+ /**
+ * 填充表格头或者体
+ *
+ * @param l
+ * @param columns
+ */
+ private void fillColumns(List 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 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 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());
+ }
+
+}
\ No newline at end of file
diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/ObjectId.java b/hutool-core/src/main/java/cn/hutool/core/lang/ObjectId.java
index bc6acdbd4..eda64d776 100644
--- a/hutool-core/src/main/java/cn/hutool/core/lang/ObjectId.java
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/ObjectId.java
@@ -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();
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/UUID.java b/hutool-core/src/main/java/cn/hutool/core/lang/UUID.java
index 0735769ab..9acdd342b 100644
--- a/hutool-core/src/main/java/cn/hutool/core/lang/UUID.java
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/UUID.java
@@ -49,7 +49,7 @@ public class UUID implements java.io.Serializable, Comparable {
* @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 {
* @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);
diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/reflect/ActualTypeMapperPool.java b/hutool-core/src/main/java/cn/hutool/core/lang/reflect/ActualTypeMapperPool.java
index 1bf09c11a..5df621904 100644
--- a/hutool-core/src/main/java/cn/hutool/core/lang/reflect/ActualTypeMapperPool.java
+++ b/hutool-core/src/main/java/cn/hutool/core/lang/reflect/ActualTypeMapperPool.java
@@ -17,7 +17,7 @@ import java.util.Map;
*/
public class ActualTypeMapperPool {
- private static final SimpleCache> cache = new SimpleCache<>();
+ private static final SimpleCache> CACHE = new SimpleCache<>();
/**
* 获取泛型变量和泛型实际类型的对应关系Map
@@ -26,7 +26,7 @@ public class ActualTypeMapperPool {
* @return 泛型对应关系Map
*/
public static Map get(Type type) {
- return cache.get(type, () -> createTypeMap(type));
+ return CACHE.get(type, () -> createTypeMap(type));
}
/**
diff --git a/hutool-core/src/main/java/cn/hutool/core/math/Money.java b/hutool-core/src/main/java/cn/hutool/core/math/Money.java
index 7845181c9..59d4288f4 100644
--- a/hutool-core/src/main/java/cn/hutool/core/math/Money.java
+++ b/hutool-core/src/main/java/cn/hutool/core/math/Money.java
@@ -67,7 +67,7 @@ public class Money implements Serializable, Comparable {
* 此处,“分”是指货币的最小单位,“元”是货币的最常用单位,
* 不同的币种有不同的元/分换算比例,如人民币是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 {
* @return 本货币币种的元/分换算比率。
*/
public int getCentFactor() {
- return centFactors[currency.getDefaultFractionDigits()];
+ return CENT_FACTORS[currency.getDefaultFractionDigits()];
}
// 基本对象方法 ===================================================
diff --git a/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java
index 108ee1635..49647d977 100644
--- a/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java
+++ b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java
@@ -11,41 +11,41 @@ import java.util.Map;
*/
public class MaskBit {
- private static final Map maskBitMap;
+ private static final Map 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);
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java b/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java
index 7aa04aaca..a27af3716 100644
--- a/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java
@@ -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}
*
diff --git a/hutool-core/src/main/java/cn/hutool/core/swing/RobotUtil.java b/hutool-core/src/main/java/cn/hutool/core/swing/RobotUtil.java
index 64abd532b..c25d7138c 100644
--- a/hutool-core/src/main/java/cn/hutool/core/swing/RobotUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/swing/RobotUtil.java
@@ -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);
}
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Escape.java b/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Escape.java
index e44b818b0..6b141626f 100644
--- a/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Escape.java
+++ b/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Escape.java
@@ -5,6 +5,8 @@ import cn.hutool.core.text.replacer.ReplacerChain;
/**
* HTML4的ESCAPE
+ * 参考:Commons Lang3
+ *
* @author looly
*
*/
diff --git a/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Unescape.java b/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Unescape.java
index b6d4de9ef..163860349 100644
--- a/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Unescape.java
+++ b/hutool-core/src/main/java/cn/hutool/core/text/escape/Html4Unescape.java
@@ -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());
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java
index e88a02322..e39bb286e 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/CharUtil.java
@@ -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之间
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ClassLoaderUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ClassLoaderUtil.java
index a7fcfd72d..dd821f44e 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/ClassLoaderUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/ClassLoaderUtil.java
@@ -33,13 +33,13 @@ public class ClassLoaderUtil {
private static final char INNER_CLASS_SEPARATOR = '$';
/** 原始类型名和其class对应表,例如:int =》 int.class */
- private static final Map> primitiveTypeNameMap = new ConcurrentHashMap<>(32);
- private static final SimpleCache> classCache = new SimpleCache<>();
+ private static final Map> PRIMITIVE_TYPE_NAME_MAP = new ConcurrentHashMap<>(32);
+ private static final SimpleCache> CLASS_CACHE = new SimpleCache<>();
static {
List> 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;
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java
index 5793cc71a..7ef8108f3 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java
@@ -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);
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
index 0dc707e64..7fdfb75e5 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
@@ -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;
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
index 190762502..2f0f95a5e 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
@@ -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
/**
- * 计算阶乘
+ * 计算范围阶乘
*
- * n! = n * (n-1) * ... * end
+ * factorial(start, end) = start * (start - 1) * ... * (end - 1)
*
*
- * @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型数字,规则如下:
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java
index b1e7081fc..59670070d 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/PageUtil.java
@@ -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) {
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ServiceLoaderUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ServiceLoaderUtil.java
index 113703285..ae7b76d93 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/ServiceLoaderUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/ServiceLoaderUtil.java
@@ -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 ServiceLoader load(Class 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 List loadList(Class clazz, ClassLoader loader) {
- return ListUtil.list(false, load(clazz));
+ return ListUtil.list(false, load(clazz, loader));
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java
index 662ac844f..c4f1e686e 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java
@@ -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
/**
- * 字符串是否为空白 空白的定义如下:
- * 1、为null
- * 2、为不可见字符(如空格)
- * 3、""
+ * 字符串是否为空白,空白的定义如下:
+ *
+ * - {@code null}
+ * - 空字符串:{@code ""}
+ * - 空格、全角空格、制表符、换行符,等不可见字符
+ *
+ *
+ * 例:
+ *
+ * - {@code StrUtil.isBlank(null) // true}
+ * - {@code StrUtil.isBlank("") // true}
+ * - {@code StrUtil.isBlank(" \t\n") // true}
+ * - {@code StrUtil.isBlank("abc") // false}
+ *
*
* @param str 被检测的字符串
- * @return 是否为空
+ * @return 若为空白,则返回 true
*/
public static boolean isBlank(CharSequence str) {
int length;
@@ -107,13 +172,25 @@ public class StrUtil {
}
/**
- * 如果对象是字符串是否为空白,空白的定义如下:
- * 1、为null
- * 2、为不可见字符(如空格)
- * 3、""
+ * 如果对象是字符串是否为空白,空白的定义如下:
+ *
+ * - {@code null}
+ * - 空字符串:{@code ""}
+ * - 空格、全角空格、制表符、换行符,等不可见字符
+ *
+ *
+ * 例:
+ *
+ * - {@code StrUtil.isBlankIfStr(null) // true}
+ * - {@code StrUtil.isBlankIfStr("") // true}
+ * - {@code StrUtil.isBlankIfStr(" \t\n") // true}
+ * - {@code StrUtil.isBlankIfStr("abc") // false}
+ *
*
* @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
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java
index 78e7a8d94..8f61aeb5d 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java
@@ -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);
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java
index 582a5a539..a78212d1c 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java
@@ -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) {
diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToNumberTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToNumberTest.java
index f8b30cf26..a1600c664 100644
--- a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToNumberTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertToNumberTest.java
@@ -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());
+ }
}
diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
index 2ded43d89..8d8d00213 100644
--- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
@@ -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;
diff --git a/hutool-core/src/test/java/cn/hutool/core/net/NetUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/net/NetUtilTest.java
index 475bd1a01..f12f4482f 100644
--- a/hutool-core/src/test/java/cn/hutool/core/net/NetUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/net/NetUtilTest.java
@@ -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());
+ }
}
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/EscapeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/EscapeUtilTest.java
index 238667630..76cb16472 100644
--- a/hutool-core/src/test/java/cn/hutool/core/util/EscapeUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/EscapeUtilTest.java
@@ -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);
+ }
}
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java
index e68df8941..dd1710807 100644
--- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java
@@ -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));
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/URLUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/URLUtilTest.java
index 2e925c164..1381a7fe8 100644
--- a/hutool-core/src/test/java/cn/hutool/core/util/URLUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/URLUtilTest.java
@@ -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);
+ }
}
diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml
index 2c62bc5a0..e1fb492f9 100644
--- a/hutool-cron/pom.xml
+++ b/hutool-cron/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.4.3
+ 5.4.4-SNAPSHOT
hutool-cron
diff --git a/hutool-cron/src/main/java/cn/hutool/cron/listener/TaskListenerManager.java b/hutool-cron/src/main/java/cn/hutool/cron/listener/TaskListenerManager.java
index 4556a55dc..ff2f5502c 100644
--- a/hutool-cron/src/main/java/cn/hutool/cron/listener/TaskListenerManager.java
+++ b/hutool-cron/src/main/java/cn/hutool/cron/listener/TaskListenerManager.java
@@ -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{
diff --git a/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java b/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java
index 2f166c2c9..569e54cd4 100644
--- a/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java
+++ b/hutool-cron/src/test/java/cn/hutool/cron/demo/CronTest.java
@@ -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();
diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml
index 1a7b014a9..e84f71c45 100644
--- a/hutool-crypto/pom.xml
+++ b/hutool-crypto/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.4.3
+ 5.4.4-SNAPSHOT
hutool-crypto
diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java
index b33f49614..d0315bd61 100644
--- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java
+++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java
@@ -499,8 +499,10 @@ public class SM2 extends AbstractAsymmetricCrypto {
*/
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 {
*/
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
diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/RC4.java b/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/RC4.java
index 2cf2e477e..13fb145f1 100644
--- a/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/RC4.java
+++ b/hutool-crypto/src/main/java/cn/hutool/crypto/symmetric/RC4.java
@@ -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加密解密算法实现
@@ -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
-}
\ No newline at end of file
+}
diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/SM2Test.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/SM2Test.java
index 40d5f12f5..42e2bcb97 100644
--- a/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/SM2Test.java
+++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/SM2Test.java
@@ -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());
+ }
+
}
diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/symmetric/RC4Test.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/symmetric/RC4Test.java
index 7869edc6a..bb9980bd5 100644
--- a/hutool-crypto/src/test/java/cn/hutool/crypto/test/symmetric/RC4Test.java
+++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/symmetric/RC4Test.java
@@ -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);
+ }
}
diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml
index afd15bb8a..991444907 100644
--- a/hutool-db/pom.xml
+++ b/hutool-db/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.4.3
+ 5.4.4-SNAPSHOT
hutool-db
diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml
index 27bf6f64d..07dc1656d 100644
--- a/hutool-dfa/pom.xml
+++ b/hutool-dfa/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.4.3
+ 5.4.4-SNAPSHOT
hutool-dfa
diff --git a/hutool-dfa/src/main/java/cn/hutool/dfa/SensitiveUtil.java b/hutool-dfa/src/main/java/cn/hutool/dfa/SensitiveUtil.java
index c61f71b61..d64100494 100644
--- a/hutool-dfa/src/main/java/cn/hutool/dfa/SensitiveUtil.java
+++ b/hutool-dfa/src/main/java/cn/hutool/dfa/SensitiveUtil.java
@@ -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);
}
+ /**
+ * 设置字符过滤规则,通过定义字符串过滤规则,过滤不需要的字符
+ * 当accept为false时,此字符不参与匹配
+ *
+ * @param charFilter 过滤函数
+ * @since 5.4.4
+ */
+ public static void setCharFilter(Filter charFilter) {
+ if(charFilter != null) {
+ sensitiveTree.setCharFilter(charFilter);
+ }
+ }
+
/**
* 是否包含敏感词
* @param text 文本
diff --git a/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java b/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java
index c576b4e7a..9aaa7b6a9 100644
--- a/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java
+++ b/hutool-dfa/src/main/java/cn/hutool/dfa/StopChar.java
@@ -11,7 +11,7 @@ import cn.hutool.core.collection.CollUtil;
*/
public class StopChar {
/** 不需要处理的词,如标点符号、空格等 */
- public static final Set STOP_WORD = CollUtil.newHashSet(new Character[] { ' ', '\'', '、', '。', //
+ public static final Set STOP_WORD = CollUtil.newHashSet(' ', '\'', '、', '。', //
'·', 'ˉ', 'ˇ', '々', '—', '~', '‖', '…', '‘', '’', '“', '”', '〔', '〕', '〈', '〉', '《', '》', '「', '」', '『', //
'』', '〖', '〗', '【', '】', '±', '+', '-', '×', '÷', '∧', '∨', '∑', '∏', '∪', '∩', '∈', '√', '⊥', '⊙', '∫', //
'∮', '≡', '≌', '≈', '∽', '∝', '≠', '≮', '≯', '≤', '≥', '∞', '∶', '∵', '∴', '∷', '♂', '♀', '°', '′', '〃', //
@@ -26,7 +26,8 @@ public class StopChar {
'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', 'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π', //
'ρ', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω', '(', ')', '〔', '〕', '^', '﹊', '﹍', '╭', '╮', '╰', '╯', '', '_', //
'', '^', '(', '^', ':', '!', '/', '\\', '\"', '<', '>', '`', '·', '。', '{', '}', '~', '~', '(', ')', '-', //
- '√', '$', '@', '*', '&', '#', '卐', '㎎', '㎏', '㎜', '㎝', '㎞', '㎡', '㏄', '㏎', '㏑', '㏒', '㏕' });
+ '√', '$', '@', '*', '&', '#', '卐', '㎎', '㎏', '㎜', '㎝', '㎞', '㎡', '㏄', '㏎', '㏑', '㏒', '㏕', '+', '=', '?',
+ ':', '.', '!', ';', ']','|','%');
/**
* 判断指定的词是否是不处理的词。 如果参数为空,则返回true,因为空也属于不处理的字符。
diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml
index e4e9f3ffa..454c0df47 100644
--- a/hutool-extra/pom.xml
+++ b/hutool-extra/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.4.3
+ 5.4.4-SNAPSHOT
hutool-extra
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java
index b1b0612dc..1a55be8a5 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java
+++ b/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java
@@ -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表情工具类
*
@@ -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);
}
/**
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java
index 8d4539793..2ae68c917 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java
+++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java
@@ -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服务器文件是否存在
*
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/GlobalMailAccount.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/GlobalMailAccount.java
index f881aeb29..ca9ab1796 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/mail/GlobalMailAccount.java
+++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/GlobalMailAccount.java
@@ -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;
}
}
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java
index 8641c990d..199c79368 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java
+++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java
@@ -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服务器域名
diff --git a/hutool-extra/src/test/java/cn/hutool/extra/emoji/EmojiUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/emoji/EmojiUtilTest.java
index fe1620c58..f307e4fe3 100644
--- a/hutool-extra/src/test/java/cn/hutool/extra/emoji/EmojiUtilTest.java
+++ b/hutool-extra/src/test/java/cn/hutool/extra/emoji/EmojiUtilTest.java
@@ -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);
+
+ }
}
diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml
index 1f6f3ead8..f5ca543b9 100644
--- a/hutool-http/pom.xml
+++ b/hutool-http/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.4.3
+ 5.4.4-SNAPSHOT
hutool-http
diff --git a/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java b/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java
index d2dfc74b6..f8358e400 100644
--- a/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java
+++ b/hutool-http/src/main/java/cn/hutool/http/webservice/SoapClient.java
@@ -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 {
* 创建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 {
*
* @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 {
* @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 {
*
* @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 {
*
* @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 {
* @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 {
* @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 {
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;
}
/**
diff --git a/hutool-http/src/test/java/cn/hutool/http/test/HtmlUtilTest.java b/hutool-http/src/test/java/cn/hutool/http/test/HtmlUtilTest.java
index 9e390f267..66eb9421e 100644
--- a/hutool-http/src/test/java/cn/hutool/http/test/HtmlUtilTest.java
+++ b/hutool-http/src/test/java/cn/hutool/http/test/HtmlUtilTest.java
@@ -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
diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml
index 2da738c75..617a9ca00 100644
--- a/hutool-json/pom.xml
+++ b/hutool-json/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.4.3
+ 5.4.4-SNAPSHOT
hutool-json
diff --git a/hutool-json/src/test/java/cn/hutool/json/Issue1101Test.java b/hutool-json/src/test/java/cn/hutool/json/Issue1101Test.java
new file mode 100644
index 000000000..cdb17b458
--- /dev/null
+++ b/hutool-json/src/test/java/cn/hutool/json/Issue1101Test.java
@@ -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 convert = Convert.convert(new TypeReference>() {
+ }, 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 children = new TreeSet<>(Comparator.comparing(o -> o.id));
+ }
+
+ @Data
+ public static class TreeNode implements Comparable {
+ private String id;
+ private String parentId;
+ private int sort;
+ private String nodeName;
+ private int type;
+ private Boolean status;
+ private String treeNodeId;
+ private TreeSet children = new TreeSet<>();
+
+ @Override
+ public int compareTo(TreeNode o) {
+ return id.compareTo(o.getId());
+ }
+ }
+}
diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml
index cb2a0d056..19429e26e 100644
--- a/hutool-log/pom.xml
+++ b/hutool-log/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.4.3
+ 5.4.4-SNAPSHOT
hutool-log
diff --git a/hutool-log/src/test/resources/log4j2.xml b/hutool-log/src/test/resources/log4j2.xml
index 62fd07ae1..0293b6473 100644
--- a/hutool-log/src/test/resources/log4j2.xml
+++ b/hutool-log/src/test/resources/log4j2.xml
@@ -10,7 +10,7 @@
-
+
diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml
index 4effed78f..6d74e4a4b 100644
--- a/hutool-poi/pom.xml
+++ b/hutool-poi/pom.xml
@@ -8,7 +8,7 @@
cn.hutool
hutool-parent
- 5.4.3
+ 5.4.4-SNAPSHOT
hutool-poi
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelExtractorUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelExtractorUtil.java
new file mode 100644
index 000000000..1b5214469
--- /dev/null
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelExtractorUtil.java
@@ -0,0 +1,46 @@
+package cn.hutool.poi.excel;
+
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.extractor.ExcelExtractor;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.extractor.XSSFExcelExtractor;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+/**
+ * {@link ExcelExtractor}工具封装
+ *
+ * @author looly
+ * @since 5.4.4
+ */
+public class ExcelExtractorUtil {
+ /**
+ * 获取 {@link ExcelExtractor} 对象
+ *
+ * @param wb {@link Workbook}
+ * @return {@link ExcelExtractor}
+ */
+ public static ExcelExtractor getExtractor(Workbook wb) {
+ ExcelExtractor extractor;
+ if (wb instanceof HSSFWorkbook) {
+ extractor = new org.apache.poi.hssf.extractor.ExcelExtractor((HSSFWorkbook) wb);
+ } else {
+ extractor = new XSSFExcelExtractor((XSSFWorkbook) wb);
+ }
+ return extractor;
+ }
+
+ /**
+ * 读取为文本格式
+ * 使用{@link ExcelExtractor} 提取Excel内容
+ *
+ * @param wb {@link Workbook}
+ * @param withSheetName 是否附带sheet名
+ * @return Excel文本
+ * @since 4.1.0
+ */
+ public static String readAsText(Workbook wb, boolean withSheetName) {
+ final ExcelExtractor extractor = getExtractor(wb);
+ extractor.setIncludeSheetNames(withSheetName);
+ return extractor.getText();
+ }
+}
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelReader.java
index 308de73b7..a8dd2c4e6 100644
--- a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelReader.java
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelReader.java
@@ -1,28 +1,22 @@
package cn.hutool.poi.excel;
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.cell.CellEditor;
import cn.hutool.poi.excel.cell.CellHandler;
import cn.hutool.poi.excel.cell.CellUtil;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import cn.hutool.poi.excel.reader.BeanSheetReader;
+import cn.hutool.poi.excel.reader.ListSheetReader;
+import cn.hutool.poi.excel.reader.MapSheetReader;
+import cn.hutool.poi.excel.reader.SheetReader;
import org.apache.poi.ss.extractor.ExcelExtractor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.extractor.XSSFExcelExtractor;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.InputStream;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -256,37 +250,31 @@ public class ExcelReader extends ExcelBase {
}
/**
- * 读取工作簿中指定的Sheet
+ * 读取工作簿中指定的Sheet,此方法会把第一行作为标题行,替换标题别名
*
* @param startRowIndex 起始行(包含,从0开始计数)
* @param endRowIndex 结束行(包含,从0开始计数)
* @return 行的集合,一行使用List表示
*/
- @SuppressWarnings({"rawtypes", "unchecked"})
public List> read(int startRowIndex, int endRowIndex) {
- checkNotClosed();
- List> resultList = new ArrayList<>();
+ return read(startRowIndex, endRowIndex, true);
+ }
- startRowIndex = Math.max(startRowIndex, this.sheet.getFirstRowNum());// 读取起始行(包含)
- endRowIndex = Math.min(endRowIndex, this.sheet.getLastRowNum());// 读取结束行(包含)
- boolean isFirstLine = true;
- List rowList;
- for (int i = startRowIndex; i <= endRowIndex; i++) {
- rowList = readRow(i);
- if (CollUtil.isNotEmpty(rowList) || false == ignoreEmptyRow) {
- if (null == rowList) {
- rowList = new ArrayList<>(0);
- }
- if (isFirstLine) {
- isFirstLine = false;
- if (MapUtil.isNotEmpty(this.headerAlias)) {
- rowList = aliasHeader(rowList);
- }
- }
- resultList.add(rowList);
- }
- }
- return resultList;
+ /**
+ * 读取工作簿中指定的Sheet
+ *
+ * @param startRowIndex 起始行(包含,从0开始计数)
+ * @param endRowIndex 结束行(包含,从0开始计数)
+ * @param aliasFirstLine 是否首行作为标题行转换别名
+ * @return 行的集合,一行使用List表示
+ * @since 5.4.4
+ */
+ public List> read(int startRowIndex, int endRowIndex, boolean aliasFirstLine) {
+ final ListSheetReader reader = new ListSheetReader(startRowIndex, endRowIndex, aliasFirstLine);
+ reader.setCellEditor(this.cellEditor);
+ reader.setIgnoreEmptyRow(this.ignoreEmptyRow);
+ reader.setHeaderAlias(headerAlias);
+ return read(reader);
}
/**
@@ -348,33 +336,11 @@ public class ExcelReader extends ExcelBase {
* @return Map的列表
*/
public List