mirror of
https://gitee.com/dromara/hutool.git
synced 2025-05-08 22:58:05 +08:00
add Base62 Inverted
This commit is contained in:
parent
3e7dd16c43
commit
9b16947508
@ -5,12 +5,14 @@
|
|||||||
# 5.8.0 (2022-03-20)
|
# 5.8.0 (2022-03-20)
|
||||||
|
|
||||||
### ❌不兼容特性
|
### ❌不兼容特性
|
||||||
* 【db 】 【不向下兼容】增加MongoDB4.x支持(pr#568@Gitee)
|
* 【db 】 【不向下兼容 】增加MongoDB4.x支持返回MongoClient变更(pr#568@Gitee)
|
||||||
* 【json 】 【可能兼容问题】修改JSONObject结构,继承自MapWrapper
|
* 【json 】 【可能兼容问题】修改JSONObject结构,继承自MapWrapper
|
||||||
* 【core 】 【可能兼容问题】BeanCopier重构,新建XXXCopier,删除XXXValueProvider
|
* 【core 】 【可能兼容问题】BeanCopier重构,新建XXXCopier,删除XXXValueProvider
|
||||||
* 【core 】 【可能兼容问题】URLEncoder废弃,URLEncoderUtil使用RFC3986
|
* 【core 】 【可能兼容问题】URLEncoder废弃,URLEncoderUtil使用RFC3986
|
||||||
* 【core 】 【可能兼容问题】Base32分离编码和解码,以便减少数据加载,支持Hex模式
|
* 【core 】 【可能兼容问题】Base32分离编码和解码,以便减少数据加载,支持Hex模式
|
||||||
* 【core 】 【不兼容问题】PunyCode参数由String改为Charsequence
|
* 【core 】 【可能兼容问题】Base58分离编码和解码
|
||||||
|
* 【core 】 【可能兼容问题】Base62分离编码和解码,增加inverted模式支持
|
||||||
|
* 【core 】 【兼容问题 】PunyCode参数由String改为Charsequence
|
||||||
|
|
||||||
### 🐣新特性
|
### 🐣新特性
|
||||||
* 【http 】 HttpRequest.form采用TableMap方式(issue#I4W427@Gitee)
|
* 【http 】 HttpRequest.form采用TableMap方式(issue#I4W427@Gitee)
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
package cn.hutool.core.codec;
|
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.FileUtil;
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.util.CharsetUtil;
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
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的编码和解码方案<br>
|
* Base62工具类,提供Base62的编码和解码方案<br>
|
||||||
*
|
*
|
||||||
@ -19,7 +19,6 @@ import cn.hutool.core.util.StrUtil;
|
|||||||
public class Base62 {
|
public class Base62 {
|
||||||
|
|
||||||
private static final Charset DEFAULT_CHARSET = CharsetUtil.CHARSET_UTF_8;
|
private static final Charset DEFAULT_CHARSET = CharsetUtil.CHARSET_UTF_8;
|
||||||
private static final Base62Codec CODEC = Base62Codec.createGmp();
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------- encode
|
// -------------------------------------------------------------------- encode
|
||||||
/**
|
/**
|
||||||
@ -50,7 +49,7 @@ public class Base62 {
|
|||||||
* @return 被加密后的字符串
|
* @return 被加密后的字符串
|
||||||
*/
|
*/
|
||||||
public static String encode(byte[] source) {
|
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));
|
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
|
// -------------------------------------------------------------------- decode
|
||||||
/**
|
/**
|
||||||
* Base62解码
|
* Base62解码
|
||||||
@ -144,6 +194,69 @@ public class Base62 {
|
|||||||
* @return 解码后的bytes
|
* @return 解码后的bytes
|
||||||
*/
|
*/
|
||||||
public static byte[] decode(byte[] base62bytes) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,66 @@ import java.io.Serializable;
|
|||||||
* @author Looly, Sebastian Ruhleder, sebastian@seruco.io
|
* @author Looly, Sebastian Ruhleder, sebastian@seruco.io
|
||||||
* @since 4.5.9
|
* @since 4.5.9
|
||||||
*/
|
*/
|
||||||
public class Base62Codec implements Encoder<byte[], byte[]>, Decoder<byte[], byte[]>, Serializable{
|
public class Base62Codec implements Encoder<byte[], byte[]>, Decoder<byte[], byte[]>, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private static final int STANDARD_BASE = 256;
|
private static final int STANDARD_BASE = 256;
|
||||||
private static final int TARGET_BASE = 62;
|
private static final int TARGET_BASE = 62;
|
||||||
|
|
||||||
|
public static Base62Codec INSTANCE = new Base62Codec();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码指定消息bytes为Base62格式的bytes
|
||||||
|
*
|
||||||
|
* @param data 被编码的消息
|
||||||
|
* @return Base62内容
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] encode(byte[] data) {
|
||||||
|
return encode(data, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码指定消息bytes为Base62格式的bytes
|
||||||
|
*
|
||||||
|
* @param data 被编码的消息
|
||||||
|
* @param useInverted 是否使用反转风格,即将GMP风格中的大小写做转换
|
||||||
|
* @return Base62内容
|
||||||
|
*/
|
||||||
|
public byte[] encode(byte[] data, boolean useInverted) {
|
||||||
|
final Base62Encoder encoder = useInverted ? Base62Encoder.INVERTED_ENCODER : Base62Encoder.GMP_ENCODER;
|
||||||
|
return encoder.encode(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解码Base62消息
|
||||||
|
*
|
||||||
|
* @param encoded Base62内容
|
||||||
|
* @return 消息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] decode(byte[] encoded) {
|
||||||
|
return decode(encoded, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解码Base62消息
|
||||||
|
*
|
||||||
|
* @param encoded Base62内容
|
||||||
|
* @param useInverted 是否使用反转风格,即将GMP风格中的大小写做转换
|
||||||
|
* @return 消息
|
||||||
|
*/
|
||||||
|
public byte[] decode(byte[] encoded, boolean useInverted) {
|
||||||
|
final Base62Decoder decoder = useInverted ? Base62Decoder.INVERTED_DECODER : Base62Decoder.GMP_DECODER;
|
||||||
|
return decoder.decode(encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base62编码器
|
||||||
|
*
|
||||||
|
* @since 5.8.0
|
||||||
|
*/
|
||||||
|
public static class Base62Encoder implements Encoder<byte[], byte[]> {
|
||||||
/**
|
/**
|
||||||
* GMP风格
|
* GMP风格
|
||||||
*/
|
*/
|
||||||
@ -46,65 +100,61 @@ public class Base62Codec implements Encoder<byte[], byte[]>, Decoder<byte[], byt
|
|||||||
'U', 'V', 'W', 'X', 'Y', 'Z' //
|
'U', 'V', 'W', 'X', 'Y', 'Z' //
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
public static Base62Encoder GMP_ENCODER = new Base62Encoder(GMP);
|
||||||
* 创建GMP风格的Base62编码解码器对象
|
public static Base62Encoder INVERTED_ENCODER = new Base62Encoder(INVERTED);
|
||||||
*
|
|
||||||
* @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[] alphabet;
|
||||||
private final byte[] lookup;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
*
|
*
|
||||||
* @param alphabet 自定义字母表
|
* @param alphabet 字符表
|
||||||
*/
|
*/
|
||||||
public Base62Codec(byte[] alphabet) {
|
public Base62Encoder(byte[] alphabet) {
|
||||||
this.alphabet = alphabet;
|
this.alphabet = alphabet;
|
||||||
lookup = new byte[256];
|
|
||||||
for (int i = 0; i < alphabet.length; i++) {
|
|
||||||
lookup[alphabet[i]] = (byte) (i & 0xFF);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 编码指定消息bytes为Base62格式的bytes
|
|
||||||
*
|
|
||||||
* @param data 被编码的消息
|
|
||||||
* @return Base62内容
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] encode(byte[] data) {
|
public byte[] encode(byte[] data) {
|
||||||
final byte[] indices = convert(data, STANDARD_BASE, TARGET_BASE);
|
final byte[] indices = convert(data, STANDARD_BASE, TARGET_BASE);
|
||||||
return translate(indices, alphabet);
|
return translate(indices, alphabet);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解码Base62消息
|
* Base62解码器
|
||||||
*
|
*
|
||||||
* @param encoded Base62内容
|
* @since 5.8.0
|
||||||
* @return 消息
|
|
||||||
*/
|
*/
|
||||||
|
public static class Base62Decoder implements Decoder<byte[], byte[]> {
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
public byte[] decode(byte[] encoded) {
|
public byte[] decode(byte[] encoded) {
|
||||||
final byte[] prepared = translate(encoded, lookup);
|
final byte[] prepared = translate(encoded, lookupTable);
|
||||||
return convert(prepared, TARGET_BASE, STANDARD_BASE);
|
return convert(prepared, TARGET_BASE, STANDARD_BASE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// region Private Methods
|
// region Private Methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按照字典转换bytes
|
* 按照字典转换bytes
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cn.hutool.core.codec;
|
package cn.hutool.core.codec;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -20,4 +21,30 @@ public class Base62Test {
|
|||||||
String decodeStr = Base62.decodeStr(encode);
|
String decodeStr = Base62.decodeStr(encode);
|
||||||
Assert.assertEquals(a, decodeStr);
|
Assert.assertEquals(a, decodeStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void encodeAndDecodeInvertedTest() {
|
||||||
|
String a = "伦家是一个非常长的字符串66";
|
||||||
|
String encode = Base62.encodeInverted(a);
|
||||||
|
Assert.assertEquals("17Vku8w4jmg8Dqf8LK9vnNKDmoEwN4RjmVA6f0xSlRRt53IkbNQO", encode);
|
||||||
|
|
||||||
|
String decodeStr = Base62.decodeStrInverted(encode);
|
||||||
|
Assert.assertEquals(a, decodeStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void encodeAndDecodeRandomTest() {
|
||||||
|
String a = RandomUtil.randomString(RandomUtil.randomInt(1000));
|
||||||
|
String encode = Base62.encode(a);
|
||||||
|
String decodeStr = Base62.decodeStr(encode);
|
||||||
|
Assert.assertEquals(a, decodeStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void encodeAndDecodeInvertedRandomTest() {
|
||||||
|
String a = RandomUtil.randomString(RandomUtil.randomInt(1000));
|
||||||
|
String encode = Base62.encodeInverted(a);
|
||||||
|
String decodeStr = Base62.decodeStrInverted(encode);
|
||||||
|
Assert.assertEquals(a, decodeStr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user