我有两个整数,如1511461841
,253093752
,表示自unix时代以来的秒+纳秒。
如何将它们组合成一个大端Buffer
?
1511461841253093752
太大而无法存储为数字,这使得这个棘手且简单地连接两个UInt32BE缓冲区也不正确。
(很明显,我想编码1511461841253093752
,不是两个单独的整数)
1511461841253093752的日志库2是60.4,因此结果应该是8个字节。
我可以通过执行253093752%256来获得第一个(最右边)字节,但我无法弄清楚如何在不使用bigint库的情况下获取第二个字节。这不可能吗?
答案 0 :(得分:1)
我认为这段代码,使用big-integer 模块,执行您的要求。我添加了一些评论来解释 发生了什么。
// Load a module to represent big integers in javascript
var bigInt = require("big-integer");
// The value that we want to represent as big endian
var num = bigInt("1511461841253093752", 10);
// First we're going to store the bytes of this value in
// little endian order
var values = [];
while (num.compare(bigInt.zero) != 0) {
values.push(num.mod("256").valueOf());
num = num.divide("256");
}
// Fill with zeros if needed.
var desiredLength = 8;
while (values.length < desiredLength) {
values.push(0);
}
// Reverse the order to get big endian order and create
// a buffer from the array
values = values.reverse();
var buf = Buffer.from(values);
// This outputs <Buffer 14 f9 ca 89 5b 72 d1 78>
console.log(buf);
答案 1 :(得分:0)
我使用big-integer库作为brm suggested在Node.js和浏览器JS中实现了这一点。
function uuid() {
const [sec,ns] = getTime();
let num = BigInt(sec + padNano(ns));
let {quotient,remainder} = num.divmod(4294967296);
let buf = Buffer.allocUnsafe(16);
buf.writeUInt32BE(quotient.valueOf(),0,true);
buf.writeUInt32BE(remainder.valueOf(),4,true);
Crypto.randomBytes(8).copy(buf, 8);
return buf;
}
function padNano(ns) {
let padLen = 9 - ns.length;
if(padLen > 0) {
return '000000000'.slice(0,padLen) + ns;
}
return String(ns);
}
export default function uuid() {
const [sec,ns] = getTime();
let num = BigInt(sec + String(ns).padStart(9,'0'));
let {quotient,remainder} = num.divmod(4294967296);
let buf = new ArrayBuffer(16);
let dataView = new DataView(buf,0,8);
dataView.setUint32(0, quotient.valueOf(), false);
dataView.setUint32(4, remainder.valueOf(), false);
let cryptView = new Uint8Array(buf, 8, 8);
crypto.getRandomValues(cryptView);
return buf;
}
正如我在问题中提到的,数字代表秒和纳秒。 1e9纳秒= 1秒,因此正确的数字上限为999999999,最多需要30位才能表示。
我没有对我的问题中的“秒”进行限制,但我们可以将它限制在32位以使数学更简单。 Unix纪元+ 2 64 纳秒= 2554年7月21日,这对于我的目的来说远远不够。
因此两个数字整齐地适合uint32。所以我们所要做的就是将它除以2 32 。左半部分是商,右半部分是余数。我们可以在两个操作中执行此操作,但是大整数对于已经称为divmod
的函数有一个方便的功能,所以我使用了它。
接下来,我们只需要使用big-endian将这两个部分写入缓冲区。幸运的是,浏览器和Node都有这方面的功能,所以我们只用两次写就可以做到。