76

我将在 Javascript 中存储大量字节值(很可能超过一百万)。如果我使用带有普通数字的普通数组,则需要 8 MB,因为数字存储为 IEEE 双精度数,但如果我可以将其存储为字节,则它将只有 1 MB。

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

4

4 回答 4

78

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

类型 值范围 大小(字节)
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.4E38 至 3.4E38 4
Float64Array -1.8E308 至 1.8E308 8
BigInt64Array -2^63 到 2^63 - 1 8
BigUint64Array 0 到 2^64 - 1 8

Stack Snippets 和JSFiddle中的演示

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

于 2012-09-08T17:11:02.147 回答
15
var array = new Uint8Array(100);    
array[10] = 256;
array[10] === 0 // true

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

var array = new Uint8Array(1024*1024*50);  // allocates 50MBytes
于 2015-11-07T03:58:01.840 回答
2

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

看到您想要支持的操作(可能表示为接口)以使问题更具体会很有趣。

于 2012-09-08T16:03:35.987 回答
0

我想要一个更准确和有用的答案来回答这个问题。这是真正的答案(如果您需要专门的字节数组,请进行相应调整;显然,数学将偏离 1 倍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"

注意:如果将此类创建为全局变量,至少在 Linux 上的 Firefox 76.0 控制台中,例如分配位(即每 1000 万次分配约 2 秒),该类的分配速度确实很慢......另一方面,如果它被创建一个变量(即),那么它的速度非常快(即每 1000 万个分配约 300 毫秒)!let bits = new BitArray(1e7);


有关更多信息,请参见此处:

请注意,我使用 Uint32Array 是因为无法直接拥有位/字节数组(您可以直接与之交互)并且因为即使有BigUint64Array,JS 也仅支持 32 位:

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

...

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

于 2020-06-10T06:20:54.783 回答