如何在 Javascript 中存储字节数组

我将在 Javascript 中存储大量字节值(最有可能超过100万)。如果我使用一个普通的数组和普通的数字,这将需要8 MB,因为数字是以 IEEE 双精度存储的,但是如果我可以以字节的形式存储它,它将只有1 MB。

出于显而易见的原因,我不想浪费那么多空间。有没有办法将字节存储为字节而不是双精度的?浏览器兼容性对我来说不是问题,只要它能在 Chrome 中工作。这是在 HTML5中,如果这有什么区别的话。

146270 次浏览

您可以将数据存储在固定大小的字符串数组中。访问字符串数组中的任何特定字符并将该字符视为字节应该是有效的。

看到您想要支持的操作(可能以接口的形式表示) ,以使问题更具体,将是一件有趣的事情。

通过使用 类型化数组,您可以存储 这些类型的数组:

类型 值范围 大小(字节)
Int8Array -128到127 1
Uint8Array 0到255 1
Uint8ClampedArray 0到255 1
Int16Array -32768至32767 2
Uint16Array 0到65535 2
Int32Array -2147483648至2147483647 4
Uint32Array 0至4294967295 4
Float32Array -3.4 E38至3.4 E38 4
Float64Array -1.8 E308至1.8 E308 8
BigInt64Array -2 ^ 63比2 ^ 63-1 8
BigUint64Array 0到2 ^ 64-1 8

JSFiddle 中的演示

var array = new Uint8Array(100);
array[42] = 10;
console.log(array[42]);

var array = new Uint8Array(100);
array[10] = 256;
array[10] === 0 // true

我在 firefox 和 chrome 中验证过,它实际上是一个字节数组:

var array = new Uint8Array(1024*1024*50);  // allocates 50MBytes

我想要这个问题有一个更精确和有用的答案。下面是真正的答案(如果您想要一个特定的 字节数组,可以相应地进行调整; 很明显,数学会偏离 8 bits : 1 byte的一个因子) :

class BitArray {
constructor(bits = 0) {
this.uints = new Uint32Array(~~(bits / 32));
}


getBit(bit) {
return (this.uints[~~(bit / 32)] & (1 << (bit % 32))) != 0 ? 1 : 0;
}


assignBit(bit, value) {
if (value) {
this.uints[~~(bit / 32)] |= (1 << (bit % 32));
} else {
this.uints[~~(bit / 32)] &= ~(1 << (bit % 32));
}
}


get size() {
return this.uints.length * 32;
}


static bitsToUints(bits) {
return ~~(bits / 32);
}
}

用法:

let bits = new BitArray(500);
for (let uint = 0; uint < bits.uints.length; ++uint) {
bits.uints[uint] = 457345834;
}
for (let bit = 0; bit < 50; ++bit) {
bits.assignBit(bit, 1);
}
str = '';
for (let bit = bits.size - 1; bit >= 0; --bit) {
str += bits.getBit(bit);
}
str;

产出:

"00011011010000101000101100101010
00011011010000101000101100101010
00011011010000101000101100101010
00011011010000101000101100101010
00011011010000101000101100101010
00011011010000101000101100101010
00011011010000101000101100101010
00011011010000101000101100101010
00011011010000101000101100101010
00011011010000101000101100101010
00011011010000101000101100101010
00011011010000101000101100101010
00011011010000101000101100101010
00011011010000111111111111111111
11111111111111111111111111111111"

注意: 这个类对于分配位(即每1000万次分配约2s)来说真的很慢。 如果它是作为一个全局变量创建的,至少在 Linux 上的 Firefox 76.0控制台中是这样... ... 另一方面,如果是作为一个变量创建的(即 let bits = new BitArray(1e7);) ,那么极快的速度(即每1000万次分配约300ms) !


欲了解更多信息,请点击这里:

注意,我使用 Uint32Array 是因为没有办法直接使用位/字节数组(您可以直接与之交互) 还有,因为即使有 BigUint64Array,JS 也只支持32位:

按位运算符将其操作数视为32位的序列

...

所有按位运算符的操作数都被转换成... 32位整数