Упаковать и распаковать байтов в строки


Мне нужно написать функцию, которая "упаковывает" массив байтов (числа от 0 до 255) в строку. Я также должны быть в состоянии совершить обратную операцию, чтобы получить мой байтовый массив из строки, что он был упакован в. Это должно быть сделано как можно быстрее. Поскольку JavaScript имеет 16-битовые строки, я упаковала два байта на символ. Вот мой код и тесты:

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));
});

И вывод, что:

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]

У меня есть несколько вещей, которые я хотел бы отзывы о:

  1. Это был первый раз, когда я использовать побитовые операторы. Вот как это должно быть сделано?
  2. Есть ли улучшения в скорости, что может быть сделано?
  3. Ребята, вы можете придумать любой способ, чтобы отменить, что в прошлом 0 байт при кодировании после декодирования массив с нечетным количеством байт? (см. Тест № 4)


Комментарии
1 ответ

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;
}

так, чтобы поставить все это вместе

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;
}

15
ответ дан 22 июля 2011 в 12:07 Источник Поделиться