JavaScript - 将UTF8编码/解码为十六进制和将十六进制编码解码为UTF8

3

在我的客户端/服务器应用程序中,我从服务器获取十六进制格式的字符串,需要将其转换为UTF8。然后,在进行一些操作后,我需要将字符串重新编码,从UTF8转换为十六进制并将其返回给服务器。

我已经构建了这个函数来解析十六进制字符串到UTF8。但是当我尝试反转此算法时,我得到完全不同的结果。

这是我的测试:

function hexToUtf8(s)
{
  return decodeURIComponent(
     s.replace(/\s+/g, '') // remove spaces
      .replace(/[0-9a-f]{2}/g, '%$&') // add '%' before each 2 characters
  );
}

function utf8ToHex(s)
{
  return encodeURIComponent(s).replace(/%/g, ""); // remove all '%' characters
}

var hex = "52656c6179204f4e214f706572617465642062792030353232";

var utf8 = hexToUtf8(hex); // result: "Relay ON!Operated by 0522" (correct value)
var hex2 = utf8ToHex(utf8); // result: "Relay20ON!Operated20by200522" (some junk)

console.log("Hex: " + hex);
console.log("UTF8: " + utf8);
console.log("Hex2: " + hex2);
console.log("Is conversion OK: " + (hex == hex2)); // false


我为您准备了一个代码片段,以便创建一个最小可复现的示例 [mcve]。 - mplungjan
你似乎忘记了hex2中的空格。 - mplungjan
encodeURIComponent 不是十六进制吗,你确定你想要的是十六进制吗? - Keith
@Keith - 我确定我想要用十六进制获取结果,但我不确定是否需要使用encodeURIComponent - Gil Epshtain
1个回答

5

你的 utf8toHex 使用 encodeURIComponent,这不会使所有内容都变成 HEX。

所以我稍微修改了一下你的 utf8toHex 来处理 HEX。

更新 忘记了 toString(16) 不会自动补零,所以如果有值小于 16 的话,比如换行符等,它将失败。 因此,为了添加 0 并切片以确保结果正确。

更新2, 使用 TextEncoder,这会比使用 charCodeAt 更好地处理 UTF-8。

function hexToUtf8(s)
{
  return decodeURIComponent(
     s.replace(/\s+/g, '') // remove spaces
      .replace(/[0-9a-f]{2}/g, '%$&') // add '%' before each 2 characters
  );
}

const utf8encoder = new TextEncoder();

function utf8ToHex(s)
{
  const rb = utf8encoder.encode(s);
  let r = '';
  for (const b of rb) {
    r += ('0' + b.toString(16)).slice(-2);
  }
  return r;
}


var hex = "d7a452656c6179204f4e214f706572617465642062792030353232";

var utf8 = hexToUtf8(hex);
var hex2 = utf8ToHex(utf8);

console.log("Hex: " + hex);
console.log("UTF8: " + utf8);
console.log("Hex2: " + hex2);
console.log("Is conversion OK: " + (hex == hex2));


在我的应用程序中实施此代码后,我发现它将无法工作。 问题出现在外语中,其中函数charCodeAt()返回具有3个或更多字符的值。例如,如果hex ='d7a4'等于UTF中的'פ'。 然后回到Hex,您将获得5e4,而这与d7a4 不相同 - Gil Epshtain
这是因为 charCodeAt() 返回的值是基于 UTF-16 而不是 UTF-8。请参阅 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt。 - Gil Epshtain
@GilEpshtain 是的,UTF8双字节字符可能会成为一个问题,我会看看能否在这里设计出更加健壮的解决方案。 - Keith
@GilEpshtain 更新使用TextEncoder,因为这确实应该是处理UTF8的正确方式,您也可以使用TextDecoder,但使用decodeURIComponent作为简单的HEX解码器似乎也可以。 - Keith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接