Pack and unpack bytes to strings
$begingroup$
I need to write a function that "packs" an array of bytes (integers between 0 and 255) into a string. I also need to be able to perform the reverse operation, to get my byte array from the string that it was packed into. This needs to be done as fast as possible. Seeing as JavaScript has 16-bit strings, I packed two bytes per character. Here is my code and tests:
function pack(bytes) {
var str = "";
for(var i = 0; i < bytes.length; i += 2) {
var char = bytes[i] << 8;
if (bytes[i + 1])
char |= bytes[i + 1];
str += String.fromCharCode(char);
}
return str;
}
function unpack(str) {
var bytes = ;
for(var i = 0; i < str.length; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8);
bytes.push(char & 0xFF);
}
return bytes;
}
var tests = [
,
[126, 0],
[0, 65],
[12, 34, 56],
[0, 50, 100, 150, 200, 250]
];
console.log("starting tests");
tests.forEach(function(v) {
var p = pack(v);
console.log(v, p, unpack(p));
});
And the output to that is:
starting tests
""
[126, 0] "縀" [126, 0]
[0, 65] "A" [0, 65]
[12, 34, 56] "ఢ㠀" [12, 34, 56, 0]
[0, 50, 100, 150, 200, 250] "2撖죺" [0, 50, 100, 150, 200, 250]
So I have a few things I'd like feedback on.
- This was the first time I used bitwise operators. Is this how it should be done?
- Are there any speed improvements that could be made?
- Can you guys think of any way to discard that last 0 byte when encoding then decoding an array with an odd number of bytes? (see test #4)
Thanks.
javascript optimization strings
$endgroup$
|
show 3 more comments
$begingroup$
I need to write a function that "packs" an array of bytes (integers between 0 and 255) into a string. I also need to be able to perform the reverse operation, to get my byte array from the string that it was packed into. This needs to be done as fast as possible. Seeing as JavaScript has 16-bit strings, I packed two bytes per character. Here is my code and tests:
function pack(bytes) {
var str = "";
for(var i = 0; i < bytes.length; i += 2) {
var char = bytes[i] << 8;
if (bytes[i + 1])
char |= bytes[i + 1];
str += String.fromCharCode(char);
}
return str;
}
function unpack(str) {
var bytes = ;
for(var i = 0; i < str.length; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8);
bytes.push(char & 0xFF);
}
return bytes;
}
var tests = [
,
[126, 0],
[0, 65],
[12, 34, 56],
[0, 50, 100, 150, 200, 250]
];
console.log("starting tests");
tests.forEach(function(v) {
var p = pack(v);
console.log(v, p, unpack(p));
});
And the output to that is:
starting tests
""
[126, 0] "縀" [126, 0]
[0, 65] "A" [0, 65]
[12, 34, 56] "ఢ㠀" [12, 34, 56, 0]
[0, 50, 100, 150, 200, 250] "2撖죺" [0, 50, 100, 150, 200, 250]
So I have a few things I'd like feedback on.
- This was the first time I used bitwise operators. Is this how it should be done?
- Are there any speed improvements that could be made?
- Can you guys think of any way to discard that last 0 byte when encoding then decoding an array with an odd number of bytes? (see test #4)
Thanks.
javascript optimization strings
$endgroup$
1
$begingroup$
Regarding 3., just add a sentinel to the end of your packed array indicating whether the final byte should be included or not.
$endgroup$
– Rafe
Jul 21 '11 at 5:17
$begingroup$
Good idea. I was gonna have 2 bytes at the beggining indicating length, but that would have limited the length to 65535. Using your method I can have more. Not that I need it, but it's always nice to break barriers.
$endgroup$
– Xeon06
Jul 21 '11 at 13:04
$begingroup$
Why on earth would you want to encode bytes on the client side? Seems like it should be something to do on the server.
$endgroup$
– Neil
Jul 21 '11 at 13:14
2
$begingroup$
Who said that was client side?
$endgroup$
– Xeon06
Jul 21 '11 at 13:52
$begingroup$
I have used this code and there seems to be a problem when passing 0 values to it, they get converted to '' omitted, making it unreliable to pack 32bit floats to a 4 chars. Is there any solution?
$endgroup$
– RenegadeMaster88
Oct 16 '12 at 15:21
|
show 3 more comments
$begingroup$
I need to write a function that "packs" an array of bytes (integers between 0 and 255) into a string. I also need to be able to perform the reverse operation, to get my byte array from the string that it was packed into. This needs to be done as fast as possible. Seeing as JavaScript has 16-bit strings, I packed two bytes per character. Here is my code and tests:
function pack(bytes) {
var str = "";
for(var i = 0; i < bytes.length; i += 2) {
var char = bytes[i] << 8;
if (bytes[i + 1])
char |= bytes[i + 1];
str += String.fromCharCode(char);
}
return str;
}
function unpack(str) {
var bytes = ;
for(var i = 0; i < str.length; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8);
bytes.push(char & 0xFF);
}
return bytes;
}
var tests = [
,
[126, 0],
[0, 65],
[12, 34, 56],
[0, 50, 100, 150, 200, 250]
];
console.log("starting tests");
tests.forEach(function(v) {
var p = pack(v);
console.log(v, p, unpack(p));
});
And the output to that is:
starting tests
""
[126, 0] "縀" [126, 0]
[0, 65] "A" [0, 65]
[12, 34, 56] "ఢ㠀" [12, 34, 56, 0]
[0, 50, 100, 150, 200, 250] "2撖죺" [0, 50, 100, 150, 200, 250]
So I have a few things I'd like feedback on.
- This was the first time I used bitwise operators. Is this how it should be done?
- Are there any speed improvements that could be made?
- Can you guys think of any way to discard that last 0 byte when encoding then decoding an array with an odd number of bytes? (see test #4)
Thanks.
javascript optimization strings
$endgroup$
I need to write a function that "packs" an array of bytes (integers between 0 and 255) into a string. I also need to be able to perform the reverse operation, to get my byte array from the string that it was packed into. This needs to be done as fast as possible. Seeing as JavaScript has 16-bit strings, I packed two bytes per character. Here is my code and tests:
function pack(bytes) {
var str = "";
for(var i = 0; i < bytes.length; i += 2) {
var char = bytes[i] << 8;
if (bytes[i + 1])
char |= bytes[i + 1];
str += String.fromCharCode(char);
}
return str;
}
function unpack(str) {
var bytes = ;
for(var i = 0; i < str.length; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8);
bytes.push(char & 0xFF);
}
return bytes;
}
var tests = [
,
[126, 0],
[0, 65],
[12, 34, 56],
[0, 50, 100, 150, 200, 250]
];
console.log("starting tests");
tests.forEach(function(v) {
var p = pack(v);
console.log(v, p, unpack(p));
});
And the output to that is:
starting tests
""
[126, 0] "縀" [126, 0]
[0, 65] "A" [0, 65]
[12, 34, 56] "ఢ㠀" [12, 34, 56, 0]
[0, 50, 100, 150, 200, 250] "2撖죺" [0, 50, 100, 150, 200, 250]
So I have a few things I'd like feedback on.
- This was the first time I used bitwise operators. Is this how it should be done?
- Are there any speed improvements that could be made?
- Can you guys think of any way to discard that last 0 byte when encoding then decoding an array with an odd number of bytes? (see test #4)
Thanks.
javascript optimization strings
javascript optimization strings
asked Jul 20 '11 at 21:14
Xeon06Xeon06
233136
233136
1
$begingroup$
Regarding 3., just add a sentinel to the end of your packed array indicating whether the final byte should be included or not.
$endgroup$
– Rafe
Jul 21 '11 at 5:17
$begingroup$
Good idea. I was gonna have 2 bytes at the beggining indicating length, but that would have limited the length to 65535. Using your method I can have more. Not that I need it, but it's always nice to break barriers.
$endgroup$
– Xeon06
Jul 21 '11 at 13:04
$begingroup$
Why on earth would you want to encode bytes on the client side? Seems like it should be something to do on the server.
$endgroup$
– Neil
Jul 21 '11 at 13:14
2
$begingroup$
Who said that was client side?
$endgroup$
– Xeon06
Jul 21 '11 at 13:52
$begingroup$
I have used this code and there seems to be a problem when passing 0 values to it, they get converted to '' omitted, making it unreliable to pack 32bit floats to a 4 chars. Is there any solution?
$endgroup$
– RenegadeMaster88
Oct 16 '12 at 15:21
|
show 3 more comments
1
$begingroup$
Regarding 3., just add a sentinel to the end of your packed array indicating whether the final byte should be included or not.
$endgroup$
– Rafe
Jul 21 '11 at 5:17
$begingroup$
Good idea. I was gonna have 2 bytes at the beggining indicating length, but that would have limited the length to 65535. Using your method I can have more. Not that I need it, but it's always nice to break barriers.
$endgroup$
– Xeon06
Jul 21 '11 at 13:04
$begingroup$
Why on earth would you want to encode bytes on the client side? Seems like it should be something to do on the server.
$endgroup$
– Neil
Jul 21 '11 at 13:14
2
$begingroup$
Who said that was client side?
$endgroup$
– Xeon06
Jul 21 '11 at 13:52
$begingroup$
I have used this code and there seems to be a problem when passing 0 values to it, they get converted to '' omitted, making it unreliable to pack 32bit floats to a 4 chars. Is there any solution?
$endgroup$
– RenegadeMaster88
Oct 16 '12 at 15:21
1
1
$begingroup$
Regarding 3., just add a sentinel to the end of your packed array indicating whether the final byte should be included or not.
$endgroup$
– Rafe
Jul 21 '11 at 5:17
$begingroup$
Regarding 3., just add a sentinel to the end of your packed array indicating whether the final byte should be included or not.
$endgroup$
– Rafe
Jul 21 '11 at 5:17
$begingroup$
Good idea. I was gonna have 2 bytes at the beggining indicating length, but that would have limited the length to 65535. Using your method I can have more. Not that I need it, but it's always nice to break barriers.
$endgroup$
– Xeon06
Jul 21 '11 at 13:04
$begingroup$
Good idea. I was gonna have 2 bytes at the beggining indicating length, but that would have limited the length to 65535. Using your method I can have more. Not that I need it, but it's always nice to break barriers.
$endgroup$
– Xeon06
Jul 21 '11 at 13:04
$begingroup$
Why on earth would you want to encode bytes on the client side? Seems like it should be something to do on the server.
$endgroup$
– Neil
Jul 21 '11 at 13:14
$begingroup$
Why on earth would you want to encode bytes on the client side? Seems like it should be something to do on the server.
$endgroup$
– Neil
Jul 21 '11 at 13:14
2
2
$begingroup$
Who said that was client side?
$endgroup$
– Xeon06
Jul 21 '11 at 13:52
$begingroup$
Who said that was client side?
$endgroup$
– Xeon06
Jul 21 '11 at 13:52
$begingroup$
I have used this code and there seems to be a problem when passing 0 values to it, they get converted to '' omitted, making it unreliable to pack 32bit floats to a 4 chars. Is there any solution?
$endgroup$
– RenegadeMaster88
Oct 16 '12 at 15:21
$begingroup$
I have used this code and there seems to be a problem when passing 0 values to it, they get converted to '' omitted, making it unreliable to pack 32bit floats to a 4 chars. Is there any solution?
$endgroup$
– RenegadeMaster88
Oct 16 '12 at 15:21
|
show 3 more comments
4 Answers
4
active
oldest
votes
$begingroup$
function pack(bytes) {
var str = "";
// You could make it faster by reading bytes.length once.
for(var i = 0; i < bytes.length; i += 2) {
// If you're using signed bytes, you probably need to mask here.
var char = bytes[i] << 8;
// (undefined | 0) === 0 so you can save a test here by doing
// var char = (bytes[i] << 8) | (bytes[i + 1] & 0xff);
if (bytes[i + 1])
char |= bytes[i + 1];
// Instead of using string += you could push char onto an array
// and take advantage of the fact that String.fromCharCode can
// take any number of arguments to do
// String.fromCharCode.apply(null, chars);
str += String.fromCharCode(char);
}
return str;
}
function unpack(str) {
var bytes = ;
for(var i = 0; i < str.length; i++) {
var char = str.charCodeAt(i);
// You can combine both these calls into one,
// bytes.push(char >>> 8, char & 0xff);
bytes.push(char >>> 8);
bytes.push(char & 0xFF);
}
return bytes;
}
so to put it all together
function pack(bytes) {
var chars = ;
for(var i = 0, n = bytes.length; i < n;) {
chars.push(((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff));
}
return String.fromCharCode.apply(null, chars);
}
function unpack(str) {
var bytes = ;
for(var i = 0, n = str.length; i < n; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8, char & 0xFF);
}
return bytes;
}
$endgroup$
3
$begingroup$
Note thatString.fromCharCode.apply(null, chars);
will throw a "RangeError: Maximum call stack size exceeded" exception in browsers using JavaScriptCore (i.e. Safari) ifchars
has a length greater than 65536, and will lock up completely on arrays slightly smaller than that. A complete solution would either push the string directly into the array or use a chunked version offromCharCode
. I suspect the former is faster in Safari. See bugs.webkit.org/show_bug.cgi?id=80797
$endgroup$
– Matthew Caruana Galizia
Mar 12 '12 at 12:03
add a comment |
$begingroup$
As for the packing loop.... this test over here: http://jsperf.com/string-fromcharcode-test
shows that:
var s = "";
for(var i=0,l=chars.length; i<l; i++)
s += String.fromCharCode(chars[i]);
is faster than:
var s = String.fromCharCode.apply(null, chars);
$endgroup$
add a comment |
$begingroup$
building on what @mike & @nik have said, here's the pack function:
function pack(bytes) {
var retStr = '';
var char, i, l;
for (var i = 0, l = bytes.length; i < l;) {
char = ((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff);
retStr += String.fromCharCode(char);
}
return retStr;
}
$endgroup$
add a comment |
$begingroup$
Nik's test is greate, but today (6 years later) the fastest code is
var s = String.fromCharCode.apply(null, chars);
It is 3x faster than for
loop! See http://jsperf.com/string-fromcharcode-test.
New contributor
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f3569%2fpack-and-unpack-bytes-to-strings%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
function pack(bytes) {
var str = "";
// You could make it faster by reading bytes.length once.
for(var i = 0; i < bytes.length; i += 2) {
// If you're using signed bytes, you probably need to mask here.
var char = bytes[i] << 8;
// (undefined | 0) === 0 so you can save a test here by doing
// var char = (bytes[i] << 8) | (bytes[i + 1] & 0xff);
if (bytes[i + 1])
char |= bytes[i + 1];
// Instead of using string += you could push char onto an array
// and take advantage of the fact that String.fromCharCode can
// take any number of arguments to do
// String.fromCharCode.apply(null, chars);
str += String.fromCharCode(char);
}
return str;
}
function unpack(str) {
var bytes = ;
for(var i = 0; i < str.length; i++) {
var char = str.charCodeAt(i);
// You can combine both these calls into one,
// bytes.push(char >>> 8, char & 0xff);
bytes.push(char >>> 8);
bytes.push(char & 0xFF);
}
return bytes;
}
so to put it all together
function pack(bytes) {
var chars = ;
for(var i = 0, n = bytes.length; i < n;) {
chars.push(((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff));
}
return String.fromCharCode.apply(null, chars);
}
function unpack(str) {
var bytes = ;
for(var i = 0, n = str.length; i < n; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8, char & 0xFF);
}
return bytes;
}
$endgroup$
3
$begingroup$
Note thatString.fromCharCode.apply(null, chars);
will throw a "RangeError: Maximum call stack size exceeded" exception in browsers using JavaScriptCore (i.e. Safari) ifchars
has a length greater than 65536, and will lock up completely on arrays slightly smaller than that. A complete solution would either push the string directly into the array or use a chunked version offromCharCode
. I suspect the former is faster in Safari. See bugs.webkit.org/show_bug.cgi?id=80797
$endgroup$
– Matthew Caruana Galizia
Mar 12 '12 at 12:03
add a comment |
$begingroup$
function pack(bytes) {
var str = "";
// You could make it faster by reading bytes.length once.
for(var i = 0; i < bytes.length; i += 2) {
// If you're using signed bytes, you probably need to mask here.
var char = bytes[i] << 8;
// (undefined | 0) === 0 so you can save a test here by doing
// var char = (bytes[i] << 8) | (bytes[i + 1] & 0xff);
if (bytes[i + 1])
char |= bytes[i + 1];
// Instead of using string += you could push char onto an array
// and take advantage of the fact that String.fromCharCode can
// take any number of arguments to do
// String.fromCharCode.apply(null, chars);
str += String.fromCharCode(char);
}
return str;
}
function unpack(str) {
var bytes = ;
for(var i = 0; i < str.length; i++) {
var char = str.charCodeAt(i);
// You can combine both these calls into one,
// bytes.push(char >>> 8, char & 0xff);
bytes.push(char >>> 8);
bytes.push(char & 0xFF);
}
return bytes;
}
so to put it all together
function pack(bytes) {
var chars = ;
for(var i = 0, n = bytes.length; i < n;) {
chars.push(((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff));
}
return String.fromCharCode.apply(null, chars);
}
function unpack(str) {
var bytes = ;
for(var i = 0, n = str.length; i < n; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8, char & 0xFF);
}
return bytes;
}
$endgroup$
3
$begingroup$
Note thatString.fromCharCode.apply(null, chars);
will throw a "RangeError: Maximum call stack size exceeded" exception in browsers using JavaScriptCore (i.e. Safari) ifchars
has a length greater than 65536, and will lock up completely on arrays slightly smaller than that. A complete solution would either push the string directly into the array or use a chunked version offromCharCode
. I suspect the former is faster in Safari. See bugs.webkit.org/show_bug.cgi?id=80797
$endgroup$
– Matthew Caruana Galizia
Mar 12 '12 at 12:03
add a comment |
$begingroup$
function pack(bytes) {
var str = "";
// You could make it faster by reading bytes.length once.
for(var i = 0; i < bytes.length; i += 2) {
// If you're using signed bytes, you probably need to mask here.
var char = bytes[i] << 8;
// (undefined | 0) === 0 so you can save a test here by doing
// var char = (bytes[i] << 8) | (bytes[i + 1] & 0xff);
if (bytes[i + 1])
char |= bytes[i + 1];
// Instead of using string += you could push char onto an array
// and take advantage of the fact that String.fromCharCode can
// take any number of arguments to do
// String.fromCharCode.apply(null, chars);
str += String.fromCharCode(char);
}
return str;
}
function unpack(str) {
var bytes = ;
for(var i = 0; i < str.length; i++) {
var char = str.charCodeAt(i);
// You can combine both these calls into one,
// bytes.push(char >>> 8, char & 0xff);
bytes.push(char >>> 8);
bytes.push(char & 0xFF);
}
return bytes;
}
so to put it all together
function pack(bytes) {
var chars = ;
for(var i = 0, n = bytes.length; i < n;) {
chars.push(((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff));
}
return String.fromCharCode.apply(null, chars);
}
function unpack(str) {
var bytes = ;
for(var i = 0, n = str.length; i < n; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8, char & 0xFF);
}
return bytes;
}
$endgroup$
function pack(bytes) {
var str = "";
// You could make it faster by reading bytes.length once.
for(var i = 0; i < bytes.length; i += 2) {
// If you're using signed bytes, you probably need to mask here.
var char = bytes[i] << 8;
// (undefined | 0) === 0 so you can save a test here by doing
// var char = (bytes[i] << 8) | (bytes[i + 1] & 0xff);
if (bytes[i + 1])
char |= bytes[i + 1];
// Instead of using string += you could push char onto an array
// and take advantage of the fact that String.fromCharCode can
// take any number of arguments to do
// String.fromCharCode.apply(null, chars);
str += String.fromCharCode(char);
}
return str;
}
function unpack(str) {
var bytes = ;
for(var i = 0; i < str.length; i++) {
var char = str.charCodeAt(i);
// You can combine both these calls into one,
// bytes.push(char >>> 8, char & 0xff);
bytes.push(char >>> 8);
bytes.push(char & 0xFF);
}
return bytes;
}
so to put it all together
function pack(bytes) {
var chars = ;
for(var i = 0, n = bytes.length; i < n;) {
chars.push(((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff));
}
return String.fromCharCode.apply(null, chars);
}
function unpack(str) {
var bytes = ;
for(var i = 0, n = str.length; i < n; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8, char & 0xFF);
}
return bytes;
}
edited Jul 22 '11 at 0:21
answered Jul 22 '11 at 0:13
Mike SamuelMike Samuel
546612
546612
3
$begingroup$
Note thatString.fromCharCode.apply(null, chars);
will throw a "RangeError: Maximum call stack size exceeded" exception in browsers using JavaScriptCore (i.e. Safari) ifchars
has a length greater than 65536, and will lock up completely on arrays slightly smaller than that. A complete solution would either push the string directly into the array or use a chunked version offromCharCode
. I suspect the former is faster in Safari. See bugs.webkit.org/show_bug.cgi?id=80797
$endgroup$
– Matthew Caruana Galizia
Mar 12 '12 at 12:03
add a comment |
3
$begingroup$
Note thatString.fromCharCode.apply(null, chars);
will throw a "RangeError: Maximum call stack size exceeded" exception in browsers using JavaScriptCore (i.e. Safari) ifchars
has a length greater than 65536, and will lock up completely on arrays slightly smaller than that. A complete solution would either push the string directly into the array or use a chunked version offromCharCode
. I suspect the former is faster in Safari. See bugs.webkit.org/show_bug.cgi?id=80797
$endgroup$
– Matthew Caruana Galizia
Mar 12 '12 at 12:03
3
3
$begingroup$
Note that
String.fromCharCode.apply(null, chars);
will throw a "RangeError: Maximum call stack size exceeded" exception in browsers using JavaScriptCore (i.e. Safari) if chars
has a length greater than 65536, and will lock up completely on arrays slightly smaller than that. A complete solution would either push the string directly into the array or use a chunked version of fromCharCode
. I suspect the former is faster in Safari. See bugs.webkit.org/show_bug.cgi?id=80797$endgroup$
– Matthew Caruana Galizia
Mar 12 '12 at 12:03
$begingroup$
Note that
String.fromCharCode.apply(null, chars);
will throw a "RangeError: Maximum call stack size exceeded" exception in browsers using JavaScriptCore (i.e. Safari) if chars
has a length greater than 65536, and will lock up completely on arrays slightly smaller than that. A complete solution would either push the string directly into the array or use a chunked version of fromCharCode
. I suspect the former is faster in Safari. See bugs.webkit.org/show_bug.cgi?id=80797$endgroup$
– Matthew Caruana Galizia
Mar 12 '12 at 12:03
add a comment |
$begingroup$
As for the packing loop.... this test over here: http://jsperf.com/string-fromcharcode-test
shows that:
var s = "";
for(var i=0,l=chars.length; i<l; i++)
s += String.fromCharCode(chars[i]);
is faster than:
var s = String.fromCharCode.apply(null, chars);
$endgroup$
add a comment |
$begingroup$
As for the packing loop.... this test over here: http://jsperf.com/string-fromcharcode-test
shows that:
var s = "";
for(var i=0,l=chars.length; i<l; i++)
s += String.fromCharCode(chars[i]);
is faster than:
var s = String.fromCharCode.apply(null, chars);
$endgroup$
add a comment |
$begingroup$
As for the packing loop.... this test over here: http://jsperf.com/string-fromcharcode-test
shows that:
var s = "";
for(var i=0,l=chars.length; i<l; i++)
s += String.fromCharCode(chars[i]);
is faster than:
var s = String.fromCharCode.apply(null, chars);
$endgroup$
As for the packing loop.... this test over here: http://jsperf.com/string-fromcharcode-test
shows that:
var s = "";
for(var i=0,l=chars.length; i<l; i++)
s += String.fromCharCode(chars[i]);
is faster than:
var s = String.fromCharCode.apply(null, chars);
answered Feb 23 '13 at 12:44
Nik AhmadNik Ahmad
311
311
add a comment |
add a comment |
$begingroup$
building on what @mike & @nik have said, here's the pack function:
function pack(bytes) {
var retStr = '';
var char, i, l;
for (var i = 0, l = bytes.length; i < l;) {
char = ((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff);
retStr += String.fromCharCode(char);
}
return retStr;
}
$endgroup$
add a comment |
$begingroup$
building on what @mike & @nik have said, here's the pack function:
function pack(bytes) {
var retStr = '';
var char, i, l;
for (var i = 0, l = bytes.length; i < l;) {
char = ((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff);
retStr += String.fromCharCode(char);
}
return retStr;
}
$endgroup$
add a comment |
$begingroup$
building on what @mike & @nik have said, here's the pack function:
function pack(bytes) {
var retStr = '';
var char, i, l;
for (var i = 0, l = bytes.length; i < l;) {
char = ((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff);
retStr += String.fromCharCode(char);
}
return retStr;
}
$endgroup$
building on what @mike & @nik have said, here's the pack function:
function pack(bytes) {
var retStr = '';
var char, i, l;
for (var i = 0, l = bytes.length; i < l;) {
char = ((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff);
retStr += String.fromCharCode(char);
}
return retStr;
}
answered May 16 '17 at 16:48
Brad KentBrad Kent
101
101
add a comment |
add a comment |
$begingroup$
Nik's test is greate, but today (6 years later) the fastest code is
var s = String.fromCharCode.apply(null, chars);
It is 3x faster than for
loop! See http://jsperf.com/string-fromcharcode-test.
New contributor
$endgroup$
add a comment |
$begingroup$
Nik's test is greate, but today (6 years later) the fastest code is
var s = String.fromCharCode.apply(null, chars);
It is 3x faster than for
loop! See http://jsperf.com/string-fromcharcode-test.
New contributor
$endgroup$
add a comment |
$begingroup$
Nik's test is greate, but today (6 years later) the fastest code is
var s = String.fromCharCode.apply(null, chars);
It is 3x faster than for
loop! See http://jsperf.com/string-fromcharcode-test.
New contributor
$endgroup$
Nik's test is greate, but today (6 years later) the fastest code is
var s = String.fromCharCode.apply(null, chars);
It is 3x faster than for
loop! See http://jsperf.com/string-fromcharcode-test.
New contributor
New contributor
answered 4 mins ago
CodrCodr
11
11
New contributor
New contributor
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f3569%2fpack-and-unpack-bytes-to-strings%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
$begingroup$
Regarding 3., just add a sentinel to the end of your packed array indicating whether the final byte should be included or not.
$endgroup$
– Rafe
Jul 21 '11 at 5:17
$begingroup$
Good idea. I was gonna have 2 bytes at the beggining indicating length, but that would have limited the length to 65535. Using your method I can have more. Not that I need it, but it's always nice to break barriers.
$endgroup$
– Xeon06
Jul 21 '11 at 13:04
$begingroup$
Why on earth would you want to encode bytes on the client side? Seems like it should be something to do on the server.
$endgroup$
– Neil
Jul 21 '11 at 13:14
2
$begingroup$
Who said that was client side?
$endgroup$
– Xeon06
Jul 21 '11 at 13:52
$begingroup$
I have used this code and there seems to be a problem when passing 0 values to it, they get converted to '' omitted, making it unreliable to pack 32bit floats to a 4 chars. Is there any solution?
$endgroup$
– RenegadeMaster88
Oct 16 '12 at 15:21