将字符串编码为十六进制

16

我有一个将字符串转换为十六进制的函数:

function encode(str){
    str = encodeURIComponent(str).split('%').join('');
    return str.toLowerCase();
}

示例:

守护村子

alert(encode('守护村子'));

输出结果为:

e5ae88e68aa4e69d91e5ad90

它支持中文字符。但是当我用英文字母进行操作时,

alert(encode('Hello World'));

输出结果为:

hello20world

我尝试使用以下方法将字符串转换为十六进制:

function String2Hex(tmp) {
    var str = '';
    for(var i = 0; i < tmp.length; i++) {
        str += tmp[i].charCodeAt(0).toString(16);
    }
    return str;
}

然后我尝试将其应用于上面的中文字符,但它输出了UTF-8 HEX:

5b8862a467515b50

而不是ANSI Hex:

e5ae88e68aa4e69d91e5ad90

我也尝试过将UTF-8转换成ANSI,但没有成功。有人能帮我吗?谢谢!


看看这个答案,我认为它可能是你正在寻找的。 - nlloyd
谢谢,但这不是答案,它类似于上面的“String2Hex”函数,提供了utf8十六进制代码,而非ansi十六进制代码。还是谢谢。 - John Pangilinan
尝试使用tmp = unescape(encodeURIComponent(str))将文本转换为latin1。 - B. Colin Tim
4
可能是Javascript:Unicode字符串转十六进制的重复。 - Lukas Eder
6个回答

25

作为一个自包含的函数式解决方案,您可以使用以下编码:

plain.split("")
     .map(c => c.charCodeAt(0).toString(16).padStart(2, "0"))
     .join("");

split在空字符串上会生成一个数组,其中每个元素包含一个字符(或者说是一个UTF-16编码)。然后我们可以将每个字符映射为其字符编码的HEX字符串。

进行解码:

hex.split(/(\w\w)/g)
   .filter(p => !!p)
   .map(c => String.fromCharCode(parseInt(c, 16)))
   .join("")

这次传递给 split 的正则表达式捕获两个字符组,但这种形式的 split 会将它们与空字符串交替分隔(在捕获的组之间的“东西”,也就是什么都没有!)。因此,使用 filter 来删除空字符串。然后,map 对每个字符进行解码。


1
@rumpel没错!我加了一个padStart - Daniel Earwicker
2
这应该是被接受的答案,因为它适用于现代浏览器和节点,并且不需要额外的库。 - Jankapunkt
嗯... "fromCharCode" 返回0到65535之间的任何内容,要正确编码它,需要4个十六进制字符,而不是2个,对吧?我认为这个答案对于包含非ASCII字符的任何字符串都不起作用... - stillwaiting

24

在 Node.js 上,您可以执行以下操作:

const myString = "This is my string to be encoded/decoded";
const encoded = Buffer.from(myString).toString('hex'); // encoded == 54686973206973206d7920737472696e6720746f20626520656e636f6465642f6465636f646564
const decoded = Buffer.from(encoded, 'hex').toString(); // decoded == "This is my string to be encoded/decoded"

14
FYI:据我所知,包括ECMA在内的任何标准机构都没有对Buffer类进行规范化。但是,它确实由Node.js提供,并且执行你想象中的功能。 - Armen Michaeli
6
不适用于浏览器。正如amn所说,它不仅没有标准化,而且它根本不存在。不幸的是,它只是一个Node.js的东西。这意味着它不能回答问题,因为显然,像OP在问题中使用的alert()函数在Node.js中没有意义,他们显然是想让它在浏览器中工作。但希望对其他想在服务器端使用它的人有所帮助... - Luc

2

这应该可以正常工作。

var str="some random string";
var result = "";
for (i=0; i<str.length; i++) {
    hex = str.charCodeAt(i).toString(16);
    result += ("000"+hex).slice(-4);
}

2

我通过下载 utf8.js 解决了这个问题。

https://github.com/mathiasbynens/utf8.js

然后使用上面的 String2Hex 函数:

alert(String2Hex(utf8.encode('守护村子')));

这让我得到了我想要的输出:

e5ae88e68aa4e69d91e5ad90


任何像我一样看这个问题的人也应该考虑以下内容:http://stackoverflow.com/questions/32965971/javascript-charcodeat-different-values-in-jsfiddle-and-in-local-file - haakym
任何不想使用第三方工具的人都可以参考以下链接获取答案:https://dev59.com/P2Ei5IYBdhLWcg3wG45o - nbi
3
这个答案并不是完全自包含的。它完全依赖于外部资源... - Lukas Eder

1

如果你想正确处理UTF8字符串,可以尝试以下方法:

function utf8ToHex(str) {
  return Array.from(str).map(c => 
    c.charCodeAt(0) < 128
      ? c.charCodeAt(0).toString(16)
      : encodeURIComponent(c).replace(/\%/g,'').toLowerCase()
  ).join('');
}

function hexToUtf8(hex) {
  return decodeURIComponent('%' + hex.match(/.{1,2}/g).join('%'));
}

演示:https://jsfiddle.net/lyquix/k2tjbrvq/

0

另一种方法来实现它

function toHex(txt){
    const encoder = new TextEncoder();
    return Array
        .from(encoder.encode(txt))
        .map(b => b.toString(16).padStart(2, '0'))
        .join('')
}

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