CodeWeed
CodeWeed

Reputation: 1071

How to convert a hex encoded UTF-8 string to a regular string?

I have a string that contains a hexadecimal encoding of a UTF-8 string.

"666f6f6c 6973686e 6573732c 20697420 77617320 74686520 65706f63 68206f66 2062656c 6965662c 20697420 77617320 74686520 65706f63 68206f66 20696e63 72656475 6c697479 2c206974 20776173 20746865 20736561 736f6e20 6f66204c 69676874 2c206974 20776173 20746865 2073656"

I need to convert it back to a regular string. How can I do it?

Upvotes: 13

Views: 22413

Answers (5)

SuperStormer
SuperStormer

Reputation: 5387

The new TextDecoder API provides a solution. Adapting junvar's answer:

let s = '666f6f6c 6973686e 6573732c';

// [102, 111, 111, 108, 105, 115, 104, 110, 101, 115, 115, 44]
let bytes = [...s.matchAll(/[0-9a-f]{2}/g)].map(a => parseInt(a[0], 16));

// TextDecoder defaults to UTF-8
console.log(new TextDecoder().decode(new Uint8Array(bytes)));

Note that this solution works on both Node.js (v8.3.0+) and a browser (caniuse) .

Upvotes: 2

junvar
junvar

Reputation: 11574

Node only solution. There's the Buffer class that can convert between data (e.g. utf bytes and utf8 strings.

Buffer.from(0x66, 0x6f, 0x6f, 0x6c).toString(); // 'fool'

So for your space-deliminated string format of bytes, you would:

let s = '666f6f6c 6973686e 6573732c';

// [102, 111, 111, 108, 105, 115, 104, 110, 101, 115, 115, 44]
let bytes = [...s.matchAll(/[^ ]{1,2}/g)].map(a => parseInt(a[0], 16));

Buffer.from(bytes).toString(); // 'foolishness,'

Upvotes: 1

Ruben Reyes
Ruben Reyes

Reputation: 773

To properly handle UTF8 you may want to try this approach:

    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: function(hex) {
      return decodeURIComponent('%' + hex.match(/.{1,2}/g).join('%'));
    }

Demo: https://jsfiddle.net/lyquix/k2tjbrvq/

Upvotes: 2

melpomene
melpomene

Reputation: 85767

var s = "666f6f6c 6973686e 6573732c 20697420 77617320 74686520 65706f63 68206f66 2062656c 6965662c 20697420 77617320 74686520 65706f63 68206f66 20696e63 72656475 6c697479 2c206974 20776173 20746865 20736561 736f6e20 6f66204c 69676874 2c206974 20776173 20746865 2073656";
var r = decodeURIComponent(s.replace(/\s+/g, '').replace(/[0-9a-f]{2}/g, '%$&'));

This solution actually handles UTF-8.

The idea is to put a % in front of every pair of hex digits (thus creating a URL encoded string), then letting decodeURIComponent handle the details (in particular, it will correctly decode multi-byte UTF-8 characters).

Upvotes: 27

Dorian Niemiec
Dorian Niemiec

Reputation: 21

Use this:

function HexToString(s) {
  var escaped = "";
  var hex = "";
  if(s.length%4 > 0) {
    for (i = 0; i < (4 - (s.length % 4)); i++) {
      hex += "0";
    }
  }
  hex += s;
  for (var i = 0; i < hex.length; i += 4) {
    escaped += "%u" + hex.charAt(i) + hex.charAt(i + 1) + hex.charAt(i + 2) + hex.charAt(i + 3);
  }
  return unescape(escaped).split(unescape("%00")).join("");
}

It's works for me.

Upvotes: -1

Related Questions