You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java实现Torrent Info Hash的URL编码问题求助

解决Torrent Info Hash的URL编码问题

需求明确:将十六进制格式的info hash(如0a85522a2f09e42f3d63a89a0d45e4589f8b904c)转换为目标URL编码格式(如%0a%85R%2a%2f%09%e4%2f%3dc%a8%9a%0dE%e4X%9f%8b%90L),且不依赖第三方库。

原代码的核心问题

你的代码逻辑完全偏离了正确路径:

  • 错误地将十六进制字符串直接按UTF-8转字节,而非把十六进制解析为info hash的原始字节数组
  • 遍历单个十六进制字符单独编码,导致每个字符(比如R)被错误拆分处理,而非对应原始字节的编码

正确实现思路

  1. 十六进制转原始字节数组:每两个十六进制字符对应一个字节(如0a转0x0A,52转0x52即ASCII字符R)
  2. 字节级URL编码:
    • 若字节对应可打印且非URL保留的ASCII字符,直接保留原字符
    • 其余情况(不可打印ASCII、URL保留字符)转换为%XX格式,XX为字节的两位小写十六进制

完整代码实现

import java.nio.charset.StandardCharsets;

public class InfoHashUrlEncoder {
    public static void main(String[] args) {
        String hexInfoHash = "0a85522a2f09e42f3d63a89a0d45e4589f8b904c";
        String encoded = encodeInfoHash(hexInfoHash);
        System.out.println(encoded); // 输出: %0a%85R%2a%2f%09%e4%2f%3dc%a8%9a%0dE%e4X%9f%8b%90L
    }

    public static String encodeInfoHash(String hexInfoHash) {
        // 校验十六进制字符串长度是否为偶数
        if (hexInfoHash.length() % 2 != 0) {
            throw new IllegalArgumentException("无效的十六进制info hash长度");
        }

        byte[] rawHash = new byte[hexInfoHash.length() / 2];
        // 把十六进制字符串转换为原始字节数组
        for (int i = 0; i < hexInfoHash.length(); i += 2) {
            String hexPair = hexInfoHash.substring(i, i + 2);
            rawHash[i / 2] = (byte) Integer.parseInt(hexPair, 16);
        }

        StringBuilder encoded = new StringBuilder();
        for (byte b : rawHash) {
            int unsignedByte = b & 0xFF; // 转换为无符号字节值,避免负数问题

            // 判断是否为可打印且非URL保留的ASCII字符
            if ((unsignedByte >= 32 && unsignedByte <= 126) 
                && !isUrlReservedChar((char) unsignedByte)) {
                encoded.append((char) unsignedByte);
            } else {
                // 转换为%XX小写格式,不足两位补0
                encoded.append('%');
                if (unsignedByte < 16) {
                    encoded.append('0');
                }
                encoded.append(Integer.toHexString(unsignedByte).toLowerCase());
            }
        }

        return encoded.toString();
    }

    // 判断是否为RFC 3986定义的URL保留字符
    private static boolean isUrlReservedChar(char c) {
        return switch (c) {
            case ':', '/', '?', '#', '[', ']', '@', '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=' -> true;
            default -> false;
        };
    }
}

代码关键点说明

  • 十六进制转字节:通过每两位截取字符串,用Integer.parseInt解析为十六进制数值后强制转成byte
  • 无符号字节处理:用b & 0xFF把字节转成0-255的整数,避免Java字节默认带符号导致的负数问题
  • URL保留字符校验:严格遵循RFC 3986标准,确保这些特殊字符被正确编码

内容的提问来源于stack exchange,提问作者Madman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 19:31:35