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 参数值。不要传整个链接,此方法只用于参数值的编码 * * @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 args) { StringBuilder sb = new StringBuilder(); for (Map.Entry 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); } }