179 lines
3.9 KiB
Java
179 lines
3.9 KiB
Java
package com.imyeyu.utils;
|
|
|
|
import com.imyeyu.java.TimiJava;
|
|
import com.imyeyu.java.bean.timi.TimiCode;
|
|
import com.imyeyu.java.bean.timi.TimiException;
|
|
|
|
import java.io.StringWriter;
|
|
import java.net.IDN;
|
|
import java.net.MalformedURLException;
|
|
import java.net.URI;
|
|
import java.net.URISyntaxException;
|
|
import java.net.URL;
|
|
import java.net.URLEncoder;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Base64;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* 编码操作
|
|
*
|
|
* @author 夜雨
|
|
* @version 2021-02-13 10:59
|
|
*/
|
|
public class Encoder {
|
|
|
|
/**
|
|
* Unicode 编码全角字符
|
|
*
|
|
* @param data 字符串
|
|
* @return 编码结果
|
|
*/
|
|
public static String unicode(String data) {
|
|
StringWriter out = new StringWriter(data.length() * 2);
|
|
for (int i = 0, l = data.length(); i < l; i++) {
|
|
char c = data.charAt(i);
|
|
String cHex = Integer.toHexString(c).toUpperCase(Locale.ENGLISH);
|
|
|
|
if (0xFFF < c) {
|
|
out.write("\\u" + cHex);
|
|
} else if (0xFF < c) {
|
|
out.write("\\u0" + cHex);
|
|
} else if (0x7F < c) {
|
|
out.write("\\u00" + cHex);
|
|
} else if (c < 32) {
|
|
switch (c) {
|
|
case '\b' -> {
|
|
out.write('\\');
|
|
out.write('b');
|
|
}
|
|
case '\n' -> {
|
|
out.write('\\');
|
|
out.write('n');
|
|
}
|
|
case '\t' -> {
|
|
out.write('\\');
|
|
out.write('t');
|
|
}
|
|
case '\f' -> {
|
|
out.write('\\');
|
|
out.write('f');
|
|
}
|
|
case '\r' -> {
|
|
out.write('\\');
|
|
out.write('r');
|
|
}
|
|
default -> {
|
|
if (0xF < c) {
|
|
out.write("\\u00" + cHex);
|
|
} else {
|
|
out.write("\\u000" + cHex);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
switch (c) {
|
|
case '\'' -> {
|
|
out.write('\\');
|
|
out.write('\'');
|
|
}
|
|
case '"' -> {
|
|
out.write('\\');
|
|
out.write('"');
|
|
}
|
|
case '\\' -> {
|
|
out.write('\\');
|
|
out.write('\\');
|
|
}
|
|
case '/' -> {
|
|
out.write('\\');
|
|
out.write('/');
|
|
}
|
|
default -> out.write(c);
|
|
}
|
|
}
|
|
}
|
|
return out.toString();
|
|
}
|
|
|
|
/**
|
|
* Base64 编码字符串
|
|
*
|
|
* @param data 字符串
|
|
* @return 编码结果
|
|
*/
|
|
public static String base64(String data) {
|
|
return base64(data.getBytes(StandardCharsets.UTF_8));
|
|
}
|
|
|
|
/**
|
|
* Base64 编码字节数据
|
|
*
|
|
* @param bytes 字节数据
|
|
* @return 编码结果
|
|
*/
|
|
public static String base64(byte[] bytes) {
|
|
return Base64.getEncoder().encodeToString(bytes);
|
|
}
|
|
|
|
/**
|
|
* 编码 URL 参数值。不要传整个链接,此方法只用于<u>参数值</u>的编码
|
|
*
|
|
* @param data URL 参数
|
|
* @return 编码结果
|
|
*/
|
|
public static String urlArg(String data) {
|
|
return URLEncoder.encode(data, StandardCharsets.UTF_8);
|
|
}
|
|
|
|
/**
|
|
* 编码 URL 参数
|
|
*
|
|
* @param args URL 参数表
|
|
* @return 编码结果
|
|
*/
|
|
public static String urlArgs(Map<String, Object> args) {
|
|
StringBuilder sb = new StringBuilder();
|
|
for (Map.Entry<String, Object> param : args.entrySet()) {
|
|
sb.append('&').append(param.getKey()).append('=').append(urlArg(param.getValue().toString()));
|
|
}
|
|
return sb.substring(1);
|
|
}
|
|
|
|
/**
|
|
* 编码 URL 链接,半角 "+" 号会使用 "%2B"
|
|
*
|
|
* @param urlStr URL 链接
|
|
* @return 编码结果
|
|
*/
|
|
public static String url(String urlStr) {
|
|
if (TimiJava.isEmpty(urlStr)) {
|
|
return "";
|
|
}
|
|
try {
|
|
URL url = new URL(urlStr);
|
|
URI uri = new URI(url.getProtocol(), url.getUserInfo(), IDN.toASCII(url.getHost()), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
|
|
return uri.toASCIIString().replace("+", "%2B");
|
|
} catch (MalformedURLException | URISyntaxException e) {
|
|
throw new TimiException(TimiCode.ERROR, e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 字节数据转 16 进制字符串
|
|
*
|
|
* @param bytes 字节数据
|
|
* @return 16 进制字符串
|
|
*/
|
|
public static String hex(byte[] bytes) {
|
|
final int l = bytes.length;
|
|
final char[] c = new char[l << 1];
|
|
for (int i = 0, j = 0; i < l; i++) {
|
|
c[j++] = Text.HEX_DIGITS_LOWER[(0xF0 & bytes[i]) >>> 4];
|
|
c[j++] = Text.HEX_DIGITS_LOWER[0x0F & bytes[i]];
|
|
}
|
|
return new String(c);
|
|
}
|
|
}
|