diff --git a/CHANGELOG.md b/CHANGELOG.md
index 70f423188..47b286e1e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,12 +5,14 @@
# 5.8.0 (2022-03-20)
### ❌不兼容特性
-* 【db 】 【不向下兼容】增加MongoDB4.x支持(pr#568@Gitee)
+* 【db 】 【不向下兼容 】增加MongoDB4.x支持返回MongoClient变更(pr#568@Gitee)
* 【json 】 【可能兼容问题】修改JSONObject结构,继承自MapWrapper
* 【core 】 【可能兼容问题】BeanCopier重构,新建XXXCopier,删除XXXValueProvider
* 【core 】 【可能兼容问题】URLEncoder废弃,URLEncoderUtil使用RFC3986
* 【core 】 【可能兼容问题】Base32分离编码和解码,以便减少数据加载,支持Hex模式
-* 【core 】 【不兼容问题】PunyCode参数由String改为Charsequence
+* 【core 】 【可能兼容问题】Base58分离编码和解码
+* 【core 】 【可能兼容问题】Base62分离编码和解码,增加inverted模式支持
+* 【core 】 【兼容问题 】PunyCode参数由String改为Charsequence
### 🐣新特性
* 【http 】 HttpRequest.form采用TableMap方式(issue#I4W427@Gitee)
diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/Base62.java b/hutool-core/src/main/java/cn/hutool/core/codec/Base62.java
index bb0454540..9f8a458b4 100644
--- a/hutool-core/src/main/java/cn/hutool/core/codec/Base62.java
+++ b/hutool-core/src/main/java/cn/hutool/core/codec/Base62.java
@@ -1,15 +1,15 @@
package cn.hutool.core.codec;
-import java.io.File;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+
/**
* Base62工具类,提供Base62的编码和解码方案
*
@@ -19,7 +19,6 @@ import cn.hutool.core.util.StrUtil;
public class Base62 {
private static final Charset DEFAULT_CHARSET = CharsetUtil.CHARSET_UTF_8;
- private static final Base62Codec CODEC = Base62Codec.createGmp();
// -------------------------------------------------------------------- encode
/**
@@ -50,7 +49,7 @@ public class Base62 {
* @return 被加密后的字符串
*/
public static String encode(byte[] source) {
- return new String(CODEC.encode(source));
+ return new String(Base62Codec.INSTANCE.encode(source));
}
/**
@@ -73,6 +72,57 @@ public class Base62 {
return encode(FileUtil.readBytes(file));
}
+ /**
+ * Base62编码(反转字母表模式)
+ *
+ * @param source 被编码的Base62字符串
+ * @return 被加密后的字符串
+ */
+ public static String encodeInverted(CharSequence source) {
+ return encodeInverted(source, DEFAULT_CHARSET);
+ }
+
+ /**
+ * Base62编码(反转字母表模式)
+ *
+ * @param source 被编码的Base62字符串
+ * @param charset 字符集
+ * @return 被加密后的字符串
+ */
+ public static String encodeInverted(CharSequence source, Charset charset) {
+ return encodeInverted(StrUtil.bytes(source, charset));
+ }
+
+ /**
+ * Base62编码(反转字母表模式)
+ *
+ * @param source 被编码的Base62字符串
+ * @return 被加密后的字符串
+ */
+ public static String encodeInverted(byte[] source) {
+ return new String(Base62Codec.INSTANCE.encode(source, true));
+ }
+
+ /**
+ * Base62编码
+ *
+ * @param in 被编码Base62的流(一般为图片流或者文件流)
+ * @return 被加密后的字符串
+ */
+ public static String encodeInverted(InputStream in) {
+ return encodeInverted(IoUtil.readBytes(in));
+ }
+
+ /**
+ * Base62编码(反转字母表模式)
+ *
+ * @param file 被编码Base62的文件
+ * @return 被加密后的字符串
+ */
+ public static String encodeInverted(File file) {
+ return encodeInverted(FileUtil.readBytes(file));
+ }
+
// -------------------------------------------------------------------- decode
/**
* Base62解码
@@ -144,6 +194,69 @@ public class Base62 {
* @return 解码后的bytes
*/
public static byte[] decode(byte[] base62bytes) {
- return CODEC.decode(base62bytes);
+ return Base62Codec.INSTANCE.decode(base62bytes);
+ }
+
+ /**
+ * Base62解码(反转字母表模式)
+ *
+ * @param source 被解码的Base62字符串
+ * @return 被加密后的字符串
+ */
+ public static String decodeStrInverted(CharSequence source) {
+ return decodeStrInverted(source, DEFAULT_CHARSET);
+ }
+
+ /**
+ * Base62解码(反转字母表模式)
+ *
+ * @param source 被解码的Base62字符串
+ * @param charset 字符集
+ * @return 被加密后的字符串
+ */
+ public static String decodeStrInverted(CharSequence source, Charset charset) {
+ return StrUtil.str(decodeInverted(source), charset);
+ }
+
+ /**
+ * Base62解码(反转字母表模式)
+ *
+ * @param Base62 被解码的Base62字符串
+ * @param destFile 目标文件
+ * @return 目标文件
+ */
+ public static File decodeToFileInverted(CharSequence Base62, File destFile) {
+ return FileUtil.writeBytes(decodeInverted(Base62), destFile);
+ }
+
+ /**
+ * Base62解码(反转字母表模式)
+ *
+ * @param base62Str 被解码的Base62字符串
+ * @param out 写出到的流
+ * @param isCloseOut 是否关闭输出流
+ */
+ public static void decodeToStreamInverted(CharSequence base62Str, OutputStream out, boolean isCloseOut) {
+ IoUtil.write(out, isCloseOut, decodeInverted(base62Str));
+ }
+
+ /**
+ * Base62解码(反转字母表模式)
+ *
+ * @param base62Str 被解码的Base62字符串
+ * @return 被加密后的字符串
+ */
+ public static byte[] decodeInverted(CharSequence base62Str) {
+ return decodeInverted(StrUtil.bytes(base62Str, DEFAULT_CHARSET));
+ }
+
+ /**
+ * 解码Base62(反转字母表模式)
+ *
+ * @param base62bytes Base62输入
+ * @return 解码后的bytes
+ */
+ public static byte[] decodeInverted(byte[] base62bytes) {
+ return Base62Codec.INSTANCE.decode(base62bytes, true);
}
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/Base62Codec.java b/hutool-core/src/main/java/cn/hutool/core/codec/Base62Codec.java
index 1272406ac..055800dd7 100644
--- a/hutool-core/src/main/java/cn/hutool/core/codec/Base62Codec.java
+++ b/hutool-core/src/main/java/cn/hutool/core/codec/Base62Codec.java
@@ -12,73 +12,13 @@ import java.io.Serializable;
* @author Looly, Sebastian Ruhleder, sebastian@seruco.io
* @since 4.5.9
*/
-public class Base62Codec implements Encoder, Decoder, Serializable{
+public class Base62Codec implements Encoder, Decoder, Serializable {
private static final long serialVersionUID = 1L;
private static final int STANDARD_BASE = 256;
private static final int TARGET_BASE = 62;
- /**
- * GMP风格
- */
- private static final byte[] GMP = { //
- '0', '1', '2', '3', '4', '5', '6', '7', //
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', //
- 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', //
- 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', //
- 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', //
- 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', //
- 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', //
- 'u', 'v', 'w', 'x', 'y', 'z' //
- };
-
- /**
- * 反转风格,即将GMP风格中的大小写做转换
- */
- private static final byte[] INVERTED = { //
- '0', '1', '2', '3', '4', '5', '6', '7', //
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', //
- 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', //
- 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', //
- 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', //
- 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', //
- 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', //
- 'U', 'V', 'W', 'X', 'Y', 'Z' //
- };
-
- /**
- * 创建GMP风格的Base62编码解码器对象
- *
- * @return Base62Codec
- */
- public static Base62Codec createGmp() {
- return new Base62Codec(GMP);
- }
-
- /**
- * 创建Inverted风格的Base62编码解码器对象
- *
- * @return Base62Codec
- */
- public static Base62Codec createInverted() {
- return new Base62Codec(INVERTED);
- }
-
- private final byte[] alphabet;
- private final byte[] lookup;
-
- /**
- * 构造
- *
- * @param alphabet 自定义字母表
- */
- public Base62Codec(byte[] alphabet) {
- this.alphabet = alphabet;
- lookup = new byte[256];
- for (int i = 0; i < alphabet.length; i++) {
- lookup[alphabet[i]] = (byte) (i & 0xFF);
- }
- }
+ public static Base62Codec INSTANCE = new Base62Codec();
/**
* 编码指定消息bytes为Base62格式的bytes
@@ -88,8 +28,19 @@ public class Base62Codec implements Encoder, Decoder, Decoder {
+ /**
+ * GMP风格
+ */
+ private static final byte[] GMP = { //
+ '0', '1', '2', '3', '4', '5', '6', '7', //
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', //
+ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', //
+ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', //
+ 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', //
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', //
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', //
+ 'u', 'v', 'w', 'x', 'y', 'z' //
+ };
+
+ /**
+ * 反转风格,即将GMP风格中的大小写做转换
+ */
+ private static final byte[] INVERTED = { //
+ '0', '1', '2', '3', '4', '5', '6', '7', //
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', //
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', //
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', //
+ 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', //
+ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', //
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', //
+ 'U', 'V', 'W', 'X', 'Y', 'Z' //
+ };
+
+ public static Base62Encoder GMP_ENCODER = new Base62Encoder(GMP);
+ public static Base62Encoder INVERTED_ENCODER = new Base62Encoder(INVERTED);
+
+ private final byte[] alphabet;
+
+ /**
+ * 构造
+ *
+ * @param alphabet 字符表
+ */
+ public Base62Encoder(byte[] alphabet) {
+ this.alphabet = alphabet;
+ }
+
+ @Override
+ public byte[] encode(byte[] data) {
+ final byte[] indices = convert(data, STANDARD_BASE, TARGET_BASE);
+ return translate(indices, alphabet);
+ }
+ }
+
+ /**
+ * Base62解码器
+ *
+ * @since 5.8.0
+ */
+ public static class Base62Decoder implements Decoder {
+
+ public static Base62Decoder GMP_DECODER = new Base62Decoder(Base62Encoder.GMP);
+ public static Base62Decoder INVERTED_DECODER = new Base62Decoder(Base62Encoder.INVERTED);
+
+ private final byte[] lookupTable;
+
+ /**
+ * 构造
+ *
+ * @param alphabet 字母表
+ */
+ public Base62Decoder(byte[] alphabet) {
+ lookupTable = new byte['z' + 1];
+ for (int i = 0; i < alphabet.length; i++) {
+ lookupTable[alphabet[i]] = (byte) i;
+ }
+ }
+
+
+ @Override
+ public byte[] decode(byte[] encoded) {
+ final byte[] prepared = translate(encoded, lookupTable);
+ return convert(prepared, TARGET_BASE, STANDARD_BASE);
+ }
}
// region Private Methods
+
/**
* 按照字典转换bytes
*
- * @param indices 内容
+ * @param indices 内容
* @param dictionary 字典
* @return 转换值
*/
@@ -125,7 +175,7 @@ public class Base62Codec implements Encoder, Decoder, Decoder