我正在开发一个包含WebSockets的项目,服务器(Node.js)和客户端(Chrome)之间的数据是使用自定义(非常简单)格式发送的,用于我设置的数据交换。
我正在以3比特的数据发送数据,因为我发送的项目都有8种可能性。数据格式如下所示:
0 1
bit index 01234567 8901...
item aaabbbcc cddd...
目前,我正在解析字节中的项目,如下所示:
var itemA = bytes[0] >> 5;
var itemB = (bytes[0] >> 2) & 7;
var itemC = (bytes[0] & 3) << 1 | bytes[1] >> 7;
var itemD = (bytes[1] >> 4) & 7;
就个人而言,这感觉太复杂了。问题是它只是复杂的,因为我得到的字节数是8的倍数。要解析3位的项目,我必须进行位移,进行AND操作,因为8不能被3整除有时甚至必须组合两个字节的部分,如itemC
。
将这些数据作为3位组而不是8位组进行读取会更有效。
我想到的是使用.toString(2)
将所有字节转换为字符串,然后使用.substring
获取长度为3的子字符串,然后使用{{转换回数字1}},但我想这不是这样做的方法,因为字符串操作很慢而且我实际上没有做任何与字符串相关的事情。
是否可以读取例如组中的位。 3而不是从字节解析它们?或者是否有更有效的方法从字节中读取位?
答案 0 :(得分:6)
二进制AND和位移操作是执行此操作的最快方法。它们很好地转换为机器代码指令。进一步提高速度的唯一方法是牺牲速度带宽,例如每个字节不要超过3位,但从您的问题判断,您可能已经考虑过并拒绝了这种权衡。
答案 1 :(得分:4)
function byte2bits(a)
{
var tmp = "";
for(var i = 128; i >= 1; i /= 2)
tmp += a&i?'1':'0';
return tmp;
}
function split2Bits(a, n)
{
var buff = "";
var b = [];
for(var i = 0; i < a.length; i++)
{
buff += byte2bits(a[i]);
while(buff.length >= n)
{
b.push(buff.substr(0, n));
buff = buff.substr(n);
}
}
return [b, buff];
}
var a, b, r;
a = [227, 142];
[b, r] = split2Bits(a, 3);
//b = ["111", "000", "111", "000", "111"];
//r = '0'; //rest of bits
答案 2 :(得分:0)
如果注意了endian-ness,则可以将其作为int或long int数组访问。 还有一种可能是不使用第3位和第7位
答案 3 :(得分:0)
我们可以通过获得适当的16位整数然后进行位移来获得我们需要的值。
很明显,要获得i-th
值,我们应该得到16位整数,其偏移量以字节为单位,符合(bits * (i + 1) - 16)/8 <= offset <= (bits * i)/8
。
让我们M=bits*i/8
,我们有M + bits/8 - 2<= offset <= M
。然后我们获得最小偏移量ceil(M + bits/8 - 2)
并通过偏移计算16位整数中第i个值的位置。我刚刚编写了以下函数
function getDataFromStream(buffer, bitsPerValue, endianness) {
var valuesCount = Math.floor(buffer.length * 8 / bitsPerValue);
var ret = new Buffer(valuesCount);
if (valuesCount > 0) {
for (var i = 0; i < valuesCount; i++) {
var offsetMin = Math.ceil(bitsPerValue * i / 8. + bitsPerValue / 8. - 2);
if (offsetMin < 0) {
offsetMin = 0;
}
if(endianness == 'BE')
var wordWithValue = buffer.readUInt16BE(offsetMin, true);
else
var wordWithValue = buffer.readUInt16LE(offsetMin, true);
var offsetInWord = bitsPerValue * i - offsetMin * 8;
var leftInWord = 16 - bitsPerValue - offsetInWord;
// then get value in the word by shifting and then remove other bits by "%"
ret[i] = (wordWithValue >> (endianness == 'BE' ? leftInWord : offsetInWord )) % Math.pow(2, bitsPerValue);
}
}
return ret;
}
以下示例从缓冲区读取8个5位值,长度为5个字节。
// buffer with 5 bytes
var xx = new Buffer(5);
xx[0] = 255;
xx[1] = 255;
xx[2] = 255;
xx[3] = 255;
xx[4] = 250;
// get data, 5bits per value.
var yy = getDataFromStream(xx, 5, 'BE');
console.log('got buffer with length='+ yy.length);
for(i = 0; i < yy.length; i++){
console.log(i+'-'+yy[i]);
}
当我启动节点test.js时,我得到了
got buffer with length=8
0-31
1-31
2-31
3-31
4-31
5-31
6-31
7-26