Node.js缓冲区翻转二进制位

4

我正在使用nodejs进行一些解码工作,有一个缓冲区:

59 19 F2 92  8C 88 88 88  89 88 EB 89  88 88 A1 8A 
88 88 88 88  89 88 A8 CD  88 88 88 DB  88 88 88 DC 
88 88 88 A5  88 88 88 BD  88 88 88 B2  88 88 88 B8 
88 88 88 B8  88 88 88 8A  88 89 89 8D  88 89 8D 8E 
88 89 89 8F  88 89 89 80  88 8C 87 88  88 88 81 88 
89 8B 82 88  8C 9C 88 88  88 85 88 8C  88 88 88 88 
87 88 89 8A  99 88 89 88  9B 88 8C 8D  88 88 88 9C 
88 8C 8D 88  88 88 9D 88  8C 8D 88 88  88 9E 88 8C 
A0 88 88 88  9F 88 94 DA  88 88 88 ED  88 88 88 FE 
88 88 88 ED  88 88 88 FA  88 88 88 FB  88 88 88 ED 
88 88 88 90  88 90 C4 88  88 88 E1 88  88 88 EF 88 
88 88 E0 88  88 88 FC 88  88 88 FB 88  88 88 91 88 
AC C4 88 88  88 ED 88 88  88 EE 88 88  88 FC 88 88 
88 A8 88 88  88 DC 88 88  88 FD 88 88  88 FA 88 88 
88 E6 88 88  88 92 88 A0  DA 88 88 88  E1 88 88 88 
EF 88 88 88  E0 88 88 88  FC 88 88 88  A8 88 88 88

需求文档指出,它使用XOR对字节进行编码,然后取补码。

因此,

59 XOR 77 => 2E (00101110) => D1 (11010001)
19 XOR 77 => 6E (01101110) => 91 (10010001)

在Node中,最好的方法是什么,以便以所需字节结束并生成缓冲区?

2个回答

3
你可以尝试这样做:
let buf = new Buffer([ 0x59, 0x19, 0xF2, 0x92 ]); // etc.
let converted = new Buffer(
    Array.from(buf)
        .map(x => x ^ 0x77)
        .map(x => ~x)
);

// output: <Buffer d1 91 7a 1a>

这可能不是最快的方式(使用Array.from而不是逐个迭代缓冲区可能更慢,我选择了两个单独的映射而不是一个,以提高可读性),但至少可以让您开始。


你会如何在一个 map 中完成这个任务? - shaun
只需将回调函数中发生的操作组合起来,所以在这种情况下使用.map(x => ~(x ^ 0x77) - dvlsg

1

dvlsg's answer在功能上非常准确,并且得到了我的赞同。

然而,正如他们所指出的那样,他们的解决方案“可能会慢一些”(对于较小的缓冲区来说可以忽略不计,但实际上要慢得多)。位运算符使用32位寄存器进行计算,但是如果按字节进行位操作,则需要进行4倍的操作。除此之外,像.map和.forEach这样的数组内置函数正在幕后执行许多繁琐和不必要的操作,用于这种低级别的计算(这些方法针对不可变性和函数式编程--在执行期间会发生很多数据复制)。

如果你正在进行二进制操作,最好采用以下方法:

// presuming `buffer` has your raw binary buffer
let wrapperUint32Array = new Uint32Array(buffer)
let end = wrapperUint32Array.length;
let i = 0;
while(i < end){
    wrapperUint32Array[i] = ~(0x77777777 ^ wrapperUint32Array[i])
    i++;
}

// your original buffer was manipulated/contains inverted bytes

需要注意的是,上述方法仅在缓冲区被4整除且没有余数的情况下有效。如果不是这样,但缓冲区中有偶数个字节,则可以使用Uint16。如果是奇数,则需要像以下示例一样使用Uint8。虽然我们将执行更多操作(类似于数组映射),但不会复制任何数据,并且使用此方法迭代仍然更快。

// presuming `buffer` has your raw binary buffer
let end = buffer.byteLength;
let i = 0;
let wrapperUint8Array = new Uint8Array(buffer)
while(i < end){
    wrapperUint8Array[i] = ~(0x77 ^ wrapperUint8Array[i])
    i++;
}

// your original buffer was manipulated/contains inverted bytes

一些关键点:

  • 我们充分利用了32位运算符
  • 缓冲区在类型化数组中共享 - 没有数据被复制
  • 缓冲区的迭代对于性能是最优的

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接