Java 实现 JavaScript 版本的 URL 编解码

发布于 2022-12-04
encodeURIComponent

encodeURIComponent

安全字符(不会被编码的字符)为 a-zA-Z0-9~_.. (实际上 JavaScript 版本的安全字符还要更多一些,不过这些字符即使编码也不会影响使用)

private static final String HEX = "0123456789ABCDEF";

public static String encodeURIComponent(String str) {  
    if (str == null) return null;  
  
    byte[] bytes = str.getBytes(StandardCharsets.UTF_8);  
    StringBuilder builder = new StringBuilder(bytes.length);  
  
    for (byte c : bytes) {  
        if (c >= 'a' ? c <= 'z' || c == '~' :  
                c >= 'A' ? c <= 'Z' || c == '_' :  
                        c >= '0' ? c <= '9' :  c == '-' || c == '.')  
            builder.append((char)c);  
        else  
            builder.append('%')  
                    .append(HEX.charAt(c >> 4 & 0xf))  
                    .append(HEX.charAt(c & 0xf));  
    }  
  
    return builder.toString();  
}

decodeURIComponent

public static String decodeURIComponent(String str) {
    if (str == null) return null;

    int length = str.length();
    byte[] bytes = new byte[length / 3];
    StringBuilder builder = new StringBuilder(length);

    for (int i = 0; i < length; ) {
        char c = str.charAt(i);
        if (c != '%') {
            builder.append(c);
            i += 1;
        } else {
            int j = 0;
            do {
                char h = str.charAt(i + 1);
                char l = str.charAt(i + 2);
                i += 3;

                h -= '0';
                if (h >= 10) {
                    h |= ' ';
                    h -= 'a' - '0';
                    if (h >= 6) throw new IllegalArgumentException();
                    h += 10;
                }

                l -= '0';
                if (l >= 10) {
                    l |= ' ';
                    l -= 'a' - '0';
                    if (l >= 6) throw new IllegalArgumentException();
                    l += 10;
                }

                bytes[j++] = (byte)(h << 4 | l);
                if (i >= length) break;
                c = str.charAt(i);
            } while (c == '%');
            builder.append(new String(bytes, 0, j, UTF_8));
        }
    }

    return builder.toString();
}

参考链接