关于网站十六进制与字符串互转实现逻辑的技术问询
为什么你的十六进制转换结果和目标网站不一致?
你遇到的核心问题是编码格式的差异:你用string.charCodeAt()拿到的是字符的UTF-16码点,而目标网站是把字符串转换成UTF-8字节序列后再转十六进制,这俩完全不是一回事儿!
先搞懂背后的编码逻辑
咱们拿你的例子"㐤㐥"来说:
- 这两个字符的Unicode码点分别是
U+3424和U+3425(十进制就是你拿到的3424、3425)。 - 当网站做转换时,它会先把这些Unicode码点编码成UTF-8字节:
U+3424属于U+0800~U+FFFF范围,UTF-8需要用3个字节表示,计算后得到字节序列0xE3 0x90 0xA4(对应十六进制"e3 90 a4")。U+3425同理,得到0xE3 0x90 0xA5(十六进制"e3 90 a5")。
- 而你用
charCodeAt()直接拿的是UTF-16编码下的码点,转十六进制自然是"3424"和"3425",和网站的UTF-8字节转换结果肯定对不上。
实现和网站一致的转换逻辑
下面给你写JavaScript的实现代码,和网站的行为完全匹配:
1. 字符串转UTF-8十六进制(带空格或不带空格)
function stringToUtf8Hex(str, addSpaces = true) { // 先把字符串转成UTF-8字节数组 const encoder = new TextEncoder(); const bytes = encoder.encode(str); // 把每个字节转成两位十六进制,再拼接 const hexArray = Array.from(bytes, byte => byte.toString(16).padStart(2, '0')); return addSpaces ? hexArray.join(' ') : hexArray.join(''); } // 测试你的例子 console.log(stringToUtf8Hex("㐤㐥")); // 输出 "e3 90 a4 e3 90 a5" console.log(stringToUtf8Hex("㐤㐥", false)); // 输出 "e390a4e390a5"
2. UTF-8十六进制转字符串(支持带空格或不带空格)
function utf8HexToString(hexStr) { // 先去掉所有空格,确保是纯十六进制字符 const cleanHex = hexStr.replace(/\s/g, ''); // 把十六进制字符串拆成每两位一组,转成字节数组 const bytes = new Uint8Array(cleanHex.length / 2); for (let i = 0; i < cleanHex.length; i += 2) { bytes[i / 2] = parseInt(cleanHex.substring(i, i + 2), 16); } // 解码UTF-8字节数组为字符串 const decoder = new TextDecoder('utf-8'); return decoder.decode(bytes); } // 测试你的例子 console.log(utf8HexToString("e3 90 a4 e3 90 a5")); // 输出 "㐤㐥" console.log(utf8HexToString("e390a4e390a5")); // 输出 "㐤㐥"
总结一下你忽略的点
你直接用charCodeAt()获取的是字符在UTF-16编码下的码点,但网站的转换是基于UTF-8字节序列的。要和网站结果一致,必须先完成"字符串→UTF-8字节数组→十六进制"的转换流程,反过来则是"十六进制→UTF-8字节数组→字符串"。
内容的提问来源于stack exchange,提问作者Noobit
相关产品推荐
相关产品推荐

