Using TextEncoder and TextDecoder
var uint8array = new TextEncoder("utf-8").encode("Plain Text");
var string = new TextDecoder().decode(uint8array);
console.log(uint8array ,string )
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Answer from PPB on Stack OverflowUsing TextEncoder and TextDecoder
var uint8array = new TextEncoder("utf-8").encode("Plain Text");
var string = new TextDecoder().decode(uint8array);
console.log(uint8array ,string )
Run code snippetEdit code snippet Hide Results Copy to answer Expand
function stringToUint(string) {
var string = btoa(unescape(encodeURIComponent(string))),
charList = string.split(''),
uintArray = [];
for (var i = 0; i < charList.length; i++) {
uintArray.push(charList[i].charCodeAt(0));
}
return new Uint8Array(uintArray);
}
function uintToString(uintArray) {
var encodedString = String.fromCharCode.apply(null, uintArray),
decodedString = decodeURIComponent(escape(atob(encodedString)));
return decodedString;
}
I have done, with some help from the internet, these little functions, they should solve your problems! Here is the working JSFiddle.
EDIT:
Since the source of the Uint8Array is external and you can't use atob you just need to remove it(working fiddle):
function uintToString(uintArray) {
var encodedString = String.fromCharCode.apply(null, uintArray),
decodedString = decodeURIComponent(escape(encodedString));
return decodedString;
}
Warning: escape and unescape is removed from web standards. See this.
Hi!
When it comes to escape and unescape, I live by two rules:
- Avoid them when you easily can.
- Otherwise, use them.
Avoiding them when you easily can:
As mentioned in the question, both escape and unescape have been deprecated. In general, one should avoid using deprecated functions.
So, if encodeURIComponent or encodeURI does the trick for you, you should use that instead of escape.
Using them when you can't easily avoid them:
Browsers will, as far as possible, strive to achieve backwards compatibility. All major browsers have already implemented escape and unescape; why would they un-implement them?
Browsers would have to redefine escapeand unescape if the new specification requires them to do so. But wait! The people who write specifications are quite smart. They too, are interested in not breaking backwards compatibility!
I realize that the above argument is weak. But trust me, ... when it comes to browsers, deprecated stuff works. This even includes deprecated HTML tags like <xmp> and <center>.
Using escape and unescape:
So naturally, the next question is, when would one use escape or unescape?
Recently, while working on CloudBrave, I had to deal with utf8, latin1 and inter-conversions.
After reading a bunch of blog posts, I realized how simple this was:
var utf8_to_latin1 = function (s) {
return unescape(encodeURIComponent(s));
};
var latin1_to_utf8 = function (s) {
return decodeURIComponent(escape(s));
};
These inter-conversions, without using escape and unescape are rather involved. By not avoiding escape and unescape, life becomes simpler.
Hope this helps.
It is never okay to use encodeURI() or encodeURIComponent(). Let's try it out:
console.log(encodeURIComponent('@#*'));
Input: @#*. Output: %40%23*. Wait, so, what exactly happened to the * character? Why wasn't that converted? Imagine this: You ask a user what file to delete and their response is *. Server-side, you convert that using encodeURIComponent() and then run rm *. Well, got news for you: using encodeURIComponent() means you just deleted all files.
Use fixedEncodeURI(), when trying to encode a complete URL (i.e., all of example.com?arg=val), as defined and further explained at the MDN encodeURI() Documentation...
function fixedEncodeURI(str) { return encodeURI(str).replace(/%5B/g, '[').replace(/%5D/g, ']'); }
Or, you may need to use use fixedEncodeURIComponent(), when trying to encode part of a URL (i.e., the arg or the val in example.com?arg=val), as defined and further explained at the MDN encodeURIComponent() Documentation...
function fixedEncodeURIComponent(str) { return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { return '%' + c.charCodeAt(0).toString(16); }); }
If you are unable to distinguish them based on the above description, I always like to simplify it with:
fixedEncodeURI(): will not encode+@?=:#;,$&to their http-encoded equivalents (as&and+are common URL operators)fixedEncodeURIComponent()will encode+@?=:#;,$&to their http-encoded equivalents.
The logic of encoding Unicode in UTF-8 is basically:
- Up to 4 bytes per character can be used. The fewest number of bytes possible is used.
- Characters up to U+007F are encoded with a single byte.
- For multibyte sequences, the number of leading 1 bits in the first byte gives the number of bytes for the character. The rest of the bits of the first byte can be used to encode bits of the character.
- The continuation bytes begin with 10, and the other 6 bits encode bits of the character.
Here's a function I wrote a while back for encoding a JavaScript UTF-16 string in UTF-8:
function toUTF8Array(str) {
var utf8 = [];
for (var i=0; i < str.length; i++) {
var charcode = str.charCodeAt(i);
if (charcode < 0x80) utf8.push(charcode);
else if (charcode < 0x800) {
utf8.push(0xc0 | (charcode >> 6),
0x80 | (charcode & 0x3f));
}
else if (charcode < 0xd800 || charcode >= 0xe000) {
utf8.push(0xe0 | (charcode >> 12),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
}
// surrogate pair
else {
i++;
// UTF-16 encodes 0x10000-0x10FFFF by
// subtracting 0x10000 and splitting the
// 20 bits of 0x0-0xFFFFF into two halves
charcode = 0x10000 + (((charcode & 0x3ff)<<10)
| (str.charCodeAt(i) & 0x3ff));
utf8.push(0xf0 | (charcode >>18),
0x80 | ((charcode>>12) & 0x3f),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
}
}
return utf8;
}
JavaScript Strings are stored in UTF-16. To get UTF-8, you'll have to convert the String yourself.
One way is to mix encodeURIComponent(), which will output UTF-8 bytes URL-encoded, with unescape, as mentioned on ecmanaut.
var utf8 = unescape(encodeURIComponent(str));
var arr = [];
for (var i = 0; i < utf8.length; i++) {
arr.push(utf8.charCodeAt(i));
}
To answer the original question: here is how you decode utf-8 in javascript:
http://ecmanaut.blogspot.ca/2006/07/encoding-decoding-utf8-in-javascript.html
Specifically,
function encode_utf8(s) {
return unescape(encodeURIComponent(s));
}
function decode_utf8(s) {
return decodeURIComponent(escape(s));
}
We have been using this in our production code for 6 years, and it has worked flawlessly.
Note, however, that escape() and unescape() are deprecated. See this.
This should work:
// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
/* utf.js - UTF-8 <=> UTF-16 convertion
*
* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
* Version: 1.0
* LastModified: Dec 25 1999
* This library is free. You can redistribute it and/or modify it.
*/
function Utf8ArrayToStr(array) {
var out, i, len, c;
var char2, char3;
out = "";
len = array.length;
i = 0;
while(i < len) {
c = array[i++];
switch(c >> 4)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
out += String.fromCharCode(c);
break;
case 12: case 13:
// 110x xxxx 10xx xxxx
char2 = array[i++];
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = array[i++];
char3 = array[i++];
out += String.fromCharCode(((c & 0x0F) << 12) |
((char2 & 0x3F) << 6) |
((char3 & 0x3F) << 0));
break;
}
}
return out;
}
Check out the JSFiddle demo.
Also see the related questions: here and here
JavaScript strings consist of UTF-16 code units, yet the numbers in your array are the bytes of a UTF-8 string. Here is one way to convert the string, which uses the decodeURIComponent() function:
var i, str = '';
for (i = 0; i < arr.length; i++) {
str += '%' + ('0' + arr[i].toString(16)).slice(-2);
}
str = decodeURIComponent(str);
Performing the UTF-8 to UTF-16 conversion in the conventional way is likely to be more efficient but would require more code.
var arry = [3,5,7,9];
console.log(arry.map(String))
the result will be ['3','5','7','9']
var arry = ['3','5','7','9']
console.log(arry.map(Number))
the result will be [3,5,7,9]