Compress alphanumeric characters with a limit of 8 bytes hex character - javascript

My application has a limit input of 16 hex characters to represent 8 ASCII characters. The only characters I need are A-Z and 0-9. I do not need lower cases or any non-standard alphanumeric characters. A 2 character hex can represent all of the characters on the keyboard, but I don't need all of it.
Is there some type of library that can compress the alphanumeric string to be able to fit it in 16 hex characters?
Example:
12345678 = 31 32 33 34 35 36 37 38
I want to be able to pack in more alphanumeric characters like this:
ABCDEFGHI12345678 = 31 32 33 34 35 36 37 38
Is there a library that does this?

After some experimentation, here's my compression algorithm.
It takes a 6-character message containing A-Z and 0-9 and turns it into 8 hex characters.
It can be used twice to compress as 12-character string into 16 hex characters.
If my math is correct, this is the best compression you can achieve, because 16^16 is almost equal to 36^(12.38), which means that you can fit at most 12 characters of a 36-character set (A-Z, 0-9) into 16 hex characters.
I hope it'll be useful for your application.
const testMessage = '6CHARS';
function charToInt(char, shift) {
let charCode = char.charCodeAt(0) - 48;
if (charCode > 9) {
charCode -= 7;
}
charCode *= 36 ** shift;
return charCode;
}
function intToChar(int, shift) {
let number = int / (36 ** shift);
if (number > 9) {
number += 7;
}
number += 48;
return String.fromCharCode(number);
}
function stringToInt(stringWithSixCharacters) {
let result = 0;
for (let index = 0; index < 6; index++) {
result += charToInt(stringWithSixCharacters.charAt(index), 5 - index);
}
return result;
}
function intToString(intFromSixCharacters) {
let number = intFromSixCharacters;
let result = '';
for (let index = 0; index < 6; index++) {
const mod = number % (36 ** (index + 1));
const char = intToChar(mod, index);
result = char + result;
number = number - mod;
}
return result;
}
function intToHex(int) {
return int.toString(16).padStart(8, '0').toUpperCase();
}
function hexToInt(hex) {
return parseInt(messageHex, 16);
}
console.log('testMessage:', testMessage);
const messageCode = stringToInt(testMessage);
const messageHex = intToHex(messageCode);
console.log('messageCode:', messageCode);
console.log('hex:', messageHex); // prints '16DFB4C8'
const extractedMessageCode = hexToInt(messageHex);
const extractedMessage = intToString(extractedMessageCode);
console.log('extractedMessageCode:', extractedMessageCode);
console.log('extractedMessage:', extractedMessage); // prints '6CHARS'

Related

Duplicating each character for all permutations of a string

This is a slightly odd/unique request. I am trying to achieve a result where e.g "yes" becomes, "yyes", "yees", "yess", "yyees", "yyess", "yyeess".
I have looked at this: Find all lowercase and uppercase combinations of a string in Javascript which completes it for capitalisation, however my understanding is prohibiting me from manipulating this into character duplication (if this method is even possible to use in this way).
export function letterDuplication(level: number, input: string){
const houseLength = input.length;
if (level == 1){
var resultsArray: string[] = [];
const letters = input.split("");
const permCount = 1 << input.length;
for (let perm = 0; perm < permCount; perm++) {
// Update the capitalization depending on the current permutation
letters.reduce((perm, letter, i) => {
if (perm & 1) {
letters[i] = (letter.slice(0, perm) + letter.slice(perm-1, perm) + letter.slice(perm));
} else {
letters[i] = (letter.slice(0, perm - 1) + letter.slice(perm, perm) + letter.slice(perm))
}
return perm >> 1;
}, perm);
var result = letters.join("");
console.log(result);
resultsArray[perm] = result;
}
If I haven't explained this particularly well please let me know and I'll clarify. I'm finding it quite the challenge!
General idea
To get the list of all words we can get from ordered array of letters, we need to get all combinations of letters, passed 1 or 2 times into word, like:
word = 'sample'
array = 's'{1,2} + 'a'{1,2} + 'm'{1,2} + 'p'{1,2} + 'l'{1,2} + 'e'{1,2}
Amount of all possible words equal to 2 ^ word.length (8 for "yes"), so we can build binary table with 8 rows that represent all posible combinations just via convering numbers from 0 to 7 (from decimal to binary):
0 -> 000
1 -> 001
2 -> 010
3 -> 011
4 -> 100
5 -> 101
6 -> 110
7 -> 111
Each decimal we can use as pattern for new word, where 0 means letter must be used once, and 1 - letter must be used twice:
0 -> 000 -> yes
1 -> 001 -> yess
2 -> 010 -> yees
3 -> 011 -> yeess
4 -> 100 -> yyes
5 -> 101 -> yyess
6 -> 110 -> yyees
7 -> 111 -> yyeess
Code
So, your code representation may looks like this:
// Initial word
const word = 'yes';
// List of all possible words
const result = [];
// Iterating (2 ^ word.length) times
for (let i = 0; i < Math.pow(2, word.length); i++) {
// Get binary pattern for each word
const bin = decToBin(i, word.length);
// Make a new word from pattern ...
let newWord = '';
for (let i = 0; i < word.length; i++) {
// ... by adding letter 1 or 2 times based on bin char value
newWord += word[i].repeat(+bin[i] ? 2 : 1);
}
result.push(newWord);
}
// Print result (all possible words)
console.log(result);
// Method for decimal to binary convertion with leading zeroes
// (always returns string with length = len)
function decToBin(x, len) {
let rem, bin = 0, i = 1;
while (x != 0) {
rem = x % 2;
x = parseInt(x / 2);
bin += rem * i;
i = i * 10;
}
bin = bin.toString();
return '0'.repeat(len - bin.length) + bin;
}
Maybe this example can help you. It's a bit not neat and not optimal, but it seems to work:
function getCombinations(word = '') {
const allCombination = [];
const generate = (n, arr, i = 0) => {
if (i === n) {
return allCombination.push([...arr]);
} else {
arr[i] = 0;
generate(n, arr, i + 1);
arr[i] = 1;
generate(n, arr, i + 1);
}
}
generate(word.length, Array(word.length).fill(0));
return allCombination.map((el) => {
return el.map((isCopy, i) => isCopy ? word[i].repeat(2) : word[i]).join('')
});
}
console.log(getCombinations('yes'));
console.log(getCombinations('cat'));

getting a string length that contains unicode character exceeding 0xffff

I’m using this character, double sharp '𝄪' which unicode is 0x1d12a.
If I use it in a string, I can’t get the correct string length:
str = "F𝄪"
str.length // returns 3, even though there are 2 characters!
How do I get the function to return the correct answer, whether or not I’m using special unicode or not ?
String.prototype.codes = function() { return [...this].length };
String.prototype.chars = function() {
let GraphemeSplitter = require('grapheme-splitter');
return (new GraphemeSplitter()).countGraphemes(this);
}
console.log("F𝄪".codes()); // 2
console.log("👩‍❤️‍💋‍👩".codes()); // 8
console.log("❤️".codes()); // 2
console.log("F𝄪".chars()); // 2
console.log("👩‍❤️‍💋‍👩".chars()); // 1
console.log("❤️".chars()); // 1
That's the function I wrote to get string length in codepoint length
function nbUnicodeLength(string){
var stringIndex = 0;
var unicodeIndex = 0;
var length = string.length;
var second;
var first;
while (stringIndex < length) {
first = string.charCodeAt(stringIndex); // returns an integer between 0 and 65535 representing the UTF-16 code unit at the given index.
if (first >= 0xD800 && first <= 0xDBFF && string.length > stringIndex + 1) {
second = string.charCodeAt(stringIndex + 1);
if (second >= 0xDC00 && second <= 0xDFFF) {
stringIndex += 2;
} else {
stringIndex += 1;
}
} else {
stringIndex += 1;
}
unicodeIndex += 1;
}
return unicodeIndex;
}
To sumarize my comments:
That's just the lenght of that string.
Some chars involve other chars as well, even if it looks like a single character. "̉mủt̉ả̉̉̉t̉ẻd̉W̉ỏ̉r̉̉d̉̉".length == 24
From this (great) blog post, they have a function that will return correct length:
function fancyCount(str){
const joiner = "\u{200D}";
const split = str.split(joiner);
let count = 0;
for(const s of split){
//removing the variation selectors
const num = Array.from(s.split(/[\ufe00-\ufe0f]/).join("")).length;
count += num;
}
//assuming the joiners are used appropriately
return count / split.length;
}
console.log(fancyCount("F𝄪") == 2) // true
Javascript (and Java) strings use UTF-16 encoding.
Unicode codepoint U+0046 (F) is encoded in UTF-16 using 1 codeunit: 0x0046
Unicode codepoint U+1D12A (𝄪) is encoded in UTF-16 using 2 codeunits (known as a "surrogate pair"): 0xD834 0xDD2A
That is why you are getting a length of 3, not 2. The length counts the number of encoded codeunits, not the number of Unicode codepoints.

Is it possible to only convert the letters and not also the numbers

Is it possible to only convert the letters after 4 numbers. With not converting the numbers also. I use charCodeAt to do this.
What I want to do is only converting letters and not the numbers. Below I also convert the numbers. I want to convert things after the first 4 characters, the letters are converted to ascii numbers.
function convertZipcodeToInteger(letters){
letters = letters;
for(var i = 0; i < letters.length; i++){
let number = letters.charCodeAt(i) % 65 + "";
if (number.length < 2)
{
number = "0" + number;
}
console.log(number);
}
} convertZipcodeToInteger('7711AD');
What I am doing right now with the code is putting 7711AD into the letters parameter. Putting them through an for loop, so it converts all the letters(and numbers) with charCodeAt. When the number.length is smaller then 2 it gets a 0 in front of it.
What I want to do is convert it to this: 77110003 this is with the converted letters. I don't want the numbers converted, because they don't need to change.
You could test if the value is a number and if not take the letter and convert it to a numerical value based 36 and pad it before returning.
function convertZipcodeToInteger(string) {
function pad2(s) { return ('00' + s.toString()).slice(-2); }
return string
.split('')
.map(function (c) {
return /\d/.test(c)
? c
: pad2(parseInt(c, 36) - 10);
})
.join('')
};
function convertZipcodeToLetter(string) {
return string.slice(0, 4) + string
.slice(4)
.split(/(?=(?:..)*$)/)
.map(function (s) { return (+s + 10).toString(36).toUpperCase(); })
.join('');
}
console.log(convertZipcodeToInteger('7711AD'));
console.log(convertZipcodeToLetter('77110003'));
Is it possible to only convert the letters after 4 numbers.
Simply start your for-loop from 4
for(var i = 4; i < letters.length; i++){ //notice var i = 4
Edit
Looks like you want to replace letters every time they occur, not necessarily after 4 numbers,
"7711AD".replace(/[a-z]/gi, function(match){ return ( "0" + match.charCodeAt( 0 ) % 65).slice( -2 ) });
Demo
"7711AD".replace(/[a-z]/gi, function(match) {
return ( "0" + match.charCodeAt(0) % 65).slice( -2 ); //ensuring that single digit is padded with 0
});
Your question is a bit hard to understand but this is what I think you are after:
it can also be done without the function with just regexp magic
first 4 charaters are numbers and should only have 0 added (eg 07)
then 2 letters which should be encoded from 0-26 and always be two charaters long
function convertZipcodeToInteger(letters){
for(var i = 0; i < letters.length; i++){
let number = letters[i];
if (i>3) { number = letters.charCodeAt(i) % 65 + ""; }
if (number.length < 2) {
number = "0" + number;
}
console.log(number);
}
} convertZipcodeToInteger('7711AD');

How can I encode/decode this proprietary checksum (Athena 16C PID controller)?

I have an Athena 16C controller that I am controlling via RS232. Its messaging protocol requires a proprietary checksum:
"CHKSUM: This is a two character Message Code Numbering System, representing the sum of all the ASCII values of all the characters (excluding the START, CHAR, the END CHAR, and the CHKSM themselves) in the message. The sum is computed using the following formula:
CHKSM = SUM(All Message Characters)%256 where % represents the modulus operator."
An example message (from their documentation) is this:
$Ø1Ø1RØ5C1<CR>
and can be broken down as:
$ [START CHAR] 01 [ID] 01 [ZONE] R [TYPE] 05 [PARAM] C1 [CHKSM] <CR> [END CHAR]
I have sent this message to the controller and it works as expected.
I am writing my code in JS and have the following that is supposed to calculate the CHKSM to put at the end of the message:
var sum = 'Ø1Ø1RØ5'
.split('')
.map(function(char) {
return char.charCodeAt(0);
})
.reduce(function(current, previous) {
return previous + current;
});
var chksm = (sum % 256);
console.log(chksm.toString(16));
The checksum should be 'C1' according to the message format. But the calculated sum is 377 which results in a checksum of 121 which equals 79 in hex.
// 0 = 48, 1 = 49, R = 82, 5 = 53 (ASCII values)
// 48 + 49 + 48 + 49 + 82 + 48 + 53 = 377
// 377 % 256 = 121 (decimal) = 79 (hex)
An engineer from Athena sent me the following VB code but I cannot understand the logic, nor the syntax particularly. Is there something basic I am missing with this problem in general?
' Covert the mod % 256 checksum to the 2 chars:
' Will set First and Second chars for encoded value. Pass in the value (Checksum mod 256)
' and where to return the 1st and 2nd chars to.
Public Sub EncodeIt(ByVal Value As Integer, ByRef FirstChar As Integer, ByRef SecondChar As Integer)
If Value > 359 Then 'Z9 = 359, absolute max possible
Value = 359
End If
'Note: backslash '\' means integer divide, not floating point!!
If Value > 99 Then
FirstChar = (Value \ 10) + 65 - 10 '65 = ascii "A"
Else
FirstChar = (Value \ 10) + 48 '48 = ascii "0"
End If
SecondChar = (Value Mod 10) + 48
End Sub
' Convert the two chars received in a message back to normal integer.
' Take the 2 chars and return a decoded integer value
Public Function DecodeIt(ByVal FirstChar As Integer, ByVal SecondChar As Integer) As Integer
'65 = ascii "A", 48 = ascii "0"
If FirstChar > 57 Then '57 = ascii "9"
Return ((FirstChar - 65 + 10) * 10) + (SecondChar - 48)
Else
Return ((FirstChar - 48) * 10) + (SecondChar - 48)
End If
End Function
The encoding from decimal to string is cutom made and not base16. This is why (121).toString(16) is not equal to C1.
From the VBA of your post the encoding/decoding functions should be:
function compute_checksum(message) {
var sum = 0;
for(var i=0; i<message.length; i++)
sum += message.charCodeAt(i);
return sum % 256;
}
function encode_checksum(value) {
value = Math.min(value, 359);
var c1 = ((value / 10) | 0) + (value > 99 ? 55 : 48);
var c2 = (value % 10) + 48;
return String.fromCharCode(c1, c2);
}
function decode_checksum(text) {
var c1 = text.charCodeAt(0);
var c2 = text.charCodeAt(1);
return (c1 > 57 ? c1 - 55 : c1 - 48) * 10 + (c2 - 48)
}
Here is a usage example:
var checksum = compute_checksum('0101R05');
console.log('checksum: ' + checksum);
var CHKSM = encode_checksum(checksum);
console.log('encoded checksum: ' + CHKSM);
console.log('decoded checksum: ' + decode_checksum(CHKSM));
I just went through this for C# and with the help of above, came up with this code that works (for me):
'reqtemp' is the string that contains controller ID#, Zone, Parameter, etc. without the start and checksum characters.
// generate checksum for Athena
int x = 0;
int sl = reqtemp.Length;
int FirstChar = 0; //checksum 1st character
int SecondChar = 0; //checksum 2nd char
string crcr; // crc for requests
for (int c = 0; c < sl; c++)
{
string sel = reqtemp.Substring(c, 1);
x = x + Convert.ToChar(sel);
}
x = x % 256; //modular 256
x = Math.Min(x, 359); // don't allow > 359
if (x > 99)
{ FirstChar = (x / 10) + 65 - 10; }
else
{ FirstChar = (x / 10) + 48; }
SecondChar = (x % 10) + 48;
crcr = Char.ConvertFromUtf32(FirstChar) + Char.ConvertFromUtf32(SecondChar);
// MessageBox.Show(crcr);
string reqtempfull = "$"+ reqtemp + crcr + (char)13;
crc.Text = reqtempfull; //display the full sp string
if (ComPort.IsOpen)
{
ComPort.Write(reqtempfull); // send it`enter code here`
}

How to decode byte of array data using javascript [duplicate]

How do I convert a byte array into a string?
I have found these functions that do the reverse:
function string2Bin(s) {
var b = new Array();
var last = s.length;
for (var i = 0; i < last; i++) {
var d = s.charCodeAt(i);
if (d < 128)
b[i] = dec2Bin(d);
else {
var c = s.charAt(i);
alert(c + ' is NOT an ASCII character');
b[i] = -1;
}
}
return b;
}
function dec2Bin(d) {
var b = '';
for (var i = 0; i < 8; i++) {
b = (d%2) + b;
d = Math.floor(d/2);
}
return b;
}
But how do I get the functions working the other way?
Thanks.
Shao
You need to parse each octet back to number, and use that value to get a character, something like this:
function bin2String(array) {
var result = "";
for (var i = 0; i < array.length; i++) {
result += String.fromCharCode(parseInt(array[i], 2));
}
return result;
}
bin2String(["01100110", "01101111", "01101111"]); // "foo"
// Using your string2Bin function to test:
bin2String(string2Bin("hello world")) === "hello world";
Edit: Yes, your current string2Bin can be written more shortly:
function string2Bin(str) {
var result = [];
for (var i = 0; i < str.length; i++) {
result.push(str.charCodeAt(i).toString(2));
}
return result;
}
But by looking at the documentation you linked, I think that the setBytesParameter method expects that the blob array contains the decimal numbers, not a bit string, so you could write something like this:
function string2Bin(str) {
var result = [];
for (var i = 0; i < str.length; i++) {
result.push(str.charCodeAt(i));
}
return result;
}
function bin2String(array) {
return String.fromCharCode.apply(String, array);
}
string2Bin('foo'); // [102, 111, 111]
bin2String(string2Bin('foo')) === 'foo'; // true
ES6 update
Now, string 'foo' also equals
String.fromCharCode(...[102, 111, 111])
Original answer
Simply apply your byte array to String.fromCharCode. For example
String.fromCharCode.apply(null, [102, 111, 111])
equals 'foo'.
MDN docs here.
Caveat: works for arrays shorter than 65535 - MDN docs here.
Try the new Text Encoding API:
// create an array view of some valid bytes
let bytesView = new Uint8Array([104, 101, 108, 108, 111]);
console.log(bytesView);
// convert bytes to string
// encoding can be specfied, defaults to utf-8 which is ascii.
let str = new TextDecoder().decode(bytesView);
console.log(str);
// convert string to bytes
// encoding can be specfied, defaults to utf-8 which is ascii.
let bytes2 = new TextEncoder().encode(str);
// look, they're the same!
console.log(bytes2);
console.log(bytesView);
This should work:
String.fromCharCode(...array);
Or
String.fromCodePoint(...array)
That string2Bin can be written even more succinctly, and without any loops, to boot!
function string2Bin ( str ) {
return str.split("").map( function( val ) {
return val.charCodeAt( 0 );
} );
}
String to byte array: "FooBar".split('').map(c => c.charCodeAt(0));
Byte array to string: [102, 111, 111, 98, 97, 114].map(c => String.fromCharCode(c)).join('');
I think this would be more efficient:
function toBinString (arr) {
var uarr = new Uint8Array(arr.map(function(x){return parseInt(x,2)}));
var strings = [], chunksize = 0xffff;
// There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want
for (var i=0; i*chunksize < uarr.length; i++){
strings.push(String.fromCharCode.apply(null, uarr.subarray(i*chunksize, (i+1)*chunksize)));
}
return strings.join('');
}
Even if I'm a bit late, I thought it would be interesting for future users to share some one-liners implementations I did using ES6.
One thing that I consider important depending on your environment or/and what you will do with with the data is to preserve the full byte value. For example, (5).toString(2) will give you 101, but the complete binary conversion is in reality 00000101, and that's why you might need to create a leftPad implementation to fill the string byte with leading zeros. But you may not need it at all, like other answers demonstrated.
If you run the below code snippet, you'll see the first output being the conversion of the abc string to a byte array and right after that the re-transformation of said array to it's corresponding string.
// For each byte in our array, retrieve the char code value of the binary value
const binArrayToString = array => array.map(byte => String.fromCharCode(parseInt(byte, 2))).join('')
// Basic left pad implementation to ensure string is on 8 bits
const leftPad = str => str.length < 8 ? (Array(8).join('0') + str).slice(-8) : str
// For each char of the string, get the int code and convert it to binary. Ensure 8 bits.
const stringToBinArray = str => str.split('').map(c => leftPad(c.charCodeAt().toString(2)))
const array = stringToBinArray('abc')
console.log(array)
console.log(binArrayToString(array))
If your array is encoded in UTF-8 and you can't use the TextDecoder API because it is not supported on IE:
You can use the FastestSmallestTextEncoderDecoder polyfill recommended by the Mozilla Developer Network website;
You can use this function also provided at the MDN website:
function utf8ArrayToString(aBytes) {
var sView = "";
for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) {
nPart = aBytes[nIdx];
sView += String.fromCharCode(
nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */
/* (nPart - 252 << 30) may be not so safe in ECMAScript! So...: */
(nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */
(nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */
(nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */
(nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */
(nPart - 192 << 6) + aBytes[++nIdx] - 128
: /* nPart < 127 ? */ /* one byte */
nPart
);
}
return sView;
}
let str = utf8ArrayToString([50,72,226,130,130,32,43,32,79,226,130,130,32,226,135,140,32,50,72,226,130,130,79]);
// Must show 2H₂ + O₂ ⇌ 2H₂O
console.log(str);
If you are using node.js you can do this:
yourByteArray.toString('base64');
Too late to answer but if your input is in form of ASCII bytes, then you could try this solution:
function convertArrToString(rArr){
//Step 1: Convert each element to character
let tmpArr = new Array();
rArr.forEach(function(element,index){
tmpArr.push(String.fromCharCode(element));
});
//Step 2: Return the string by joining the elements
return(tmpArr.join(""));
}
function convertArrToHexNumber(rArr){
return(parseInt(convertArrToString(rArr),16));
}
I had some decrypted byte arrays with padding characters and other stuff I didn't need, so I did this (probably not perfect, but it works for my limited use)
var junk = String.fromCharCode.apply(null, res).split('').map(char => char.charCodeAt(0) <= 127 && char.charCodeAt(0) >= 32 ? char : '').join('');
> const stringToBin = (str) => [...str].map(item=>item.charCodeAt())
> undefined
> stringToBin('hello')
> (5) [104, 101, 108, 108, 111]
> const binToString = (array) => String.fromCharCode(...array)
> undefined
> binToString(stringToBin('hello'))
> 'hello'
What you are looking for is String.fromCharCode
What you want to do is loop through the array of bytes (represented as integers), create the string equivalent and add it to the result:
function bin2String(array) {
var result = "";
for (const char of array) {
result += String.fromCharCode(char);
}
return result;
}
console.log(bin2String([116, 104, 101, 32, 114, 101, 115, 117, 108, 116]));
You can also use the Array.Map function to convert the array of bytes into an array of strings, then join them all.
function string2Bin(array) {
return array.map(byte => String.fromCharCode(byte)).join("");
}
console.log(string2Bin([116, 104, 101, 32, 114, 101, 115, 117, 108, 116]));
UPDATE
#rosberg-linhares posted best solution so far to handle UTF8.
Didn't find any solution that would work with UTF-8 characters. String.fromCharCode is good until you meet 2 byte character.
For example word Hüser can come over the wire in form of arraybuffer as [0x48,0xc3,0xbc,0x73,0x65,0x72] (e.g. through websocket connection)
But if you go through it with String.fromCharCode you will have Hüser as each byte will be converted to a char separately, and letter ü is encoded in two bytes.
Solution
Currently I'm using following solution:
function pad(n) { return (n.length < 2 ? '0' + n : n); }
function decodeUtf8(data) {
return decodeURIComponent(
data.map(byte => ('%' + pad(byte.toString(16)))).join('')
);
}
The simplest solution I've found is:
var text = atob(byteArray);

Categories