nodejs 将 64 位无符号整数写入缓冲区
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14730980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
nodejs write 64bit unsigned integer to buffer
提问by bodokaiser
I want to store a 64bit (8 byte) big integer to a nodejs buffer object in big endian format.
我想以大端格式将 64 位(8 字节)大整数存储到 nodejs 缓冲区对象中。
The problem about this task is that nodejs buffer only supports writing 32bit integers as maximum (with buf.write32UInt32BE(value, offset)). So I thought, why can't we just split the 64bit integer?
这个任务的问题是 nodejs 缓冲区只支持写入 32 位整数作为最大值(使用 buf.write32UInt32BE(value, offset))。所以我想,为什么我们不能只拆分 64 位整数呢?
var buf = new Buffer(8);
buf.fill(0) // clear all bytes of the buffer
console.log(buf); // outputs <Buffer 00 00 00 00 00 00 00 00>
var int = 0xffff; // as dezimal: 65535
buf.write32UInt32BE(0xff, 4); // right the first part of the int
console.log(buf); // outputs <Buffer 00 00 00 00 00 00 00 ff>
buf.write32UInt32BE(0xff, 0); // right the second part of the int
console.log(buf); // outputs <Buffer 00 00 00 ff 00 00 00 ff>
var bufInt = buf.read32UInt32BE(0) * buf.read32UInt32BE(4);
console.log(bufInt); // outputs 65025
As you see this nearly works. The problem is just splitting the 64bit integer and finding the missing 510 at reading it. Would somebody mind showing the solutions for these two issues?
正如你所看到的,这几乎有效。问题只是拆分 64 位整数并在读取它时找到丢失的 510。有人会介意展示这两个问题的解决方案吗?
回答by Chad
I think what you are looking for is:
我认为你正在寻找的是:
var bufInt = (buf.readUInt32BE(0) << 8) + buf.readUInt32BE(4);
Shift the first number by 8 bits and add (instead of multiplying), wich returns 65535
将第一个数字移动 8 位并添加(而不是乘法),返回 65535
EDIT
编辑
Another way to write would be:
另一种写法是:
var buf = new Buffer(8);
buf.fill(0);
var i = 0xCDEF; // 52719 in decimal
buf.writeUInt32BE(i >> 8, 0); //write the high order bits (shifted over)
buf.writeUInt32BE(i & 0x00ff, 4); //write the low order bits
console.log(buf); //displays: <Buffer 00 00 00 cd 00 00 00 ef>
var bufInt = (buf.readUInt32BE(0) << 8) + buf.readUInt32BE(4);
console.log(bufInt); //displays: 52719
回答by dash1e
Reading and writings UINT numbers up to Number.MAX_SAFE_INTEGER.
读取和写入 UINT 数字高达Number.MAX_SAFE_INTEGER.
This works in node.js only, is not portable on browser side.
这仅适用于 node.js,在浏览器端不可移植。
function uintToBase62(n) {
if (n < 0) throw 'unsupported negative integer';
let uintBuffer;
if (n < 0x7FFFFFFF) {
uintBuffer = new Buffer(4);
uintBuffer.writeUInt32BE(n, 0);
} else {
// `~~` double bitwise operator
// The most practical way of utilizing the power of this operator is to use it as a replacement
// for Math.floor() function as double bitwise NOT performs the same operation a lot quicker.
// You can use it, to convert any floating point number to a integer without performance overkill
// that comes with Math.floor(). Additionally, when you care about minification of your code,
// you end up using 2 characters (2 tildes) instead of 12.
// http://rocha.la/JavaScript-bitwise-operators-in-practice
const big = ~~(n / 0x0100000000);
const low = (n % 0x0100000000);
uintBuffer = new Buffer(8);
uintBuffer.writeUInt32BE(big, 0);
uintBuffer.writeUInt32BE(low, 4);
}
return uintBuffer.toString('hex');
}
to convert it
转换它
function uintFromBase62(uintBuffer) {
const n = parseInt(uintBuffer.toString('hex'), 16);
return n;
}
回答by loganfsmyth
I'm confused because your example value of 0xFFFFis only 16-bit, not 64-bit.
我很困惑,因为您的示例值0xFFFF只有 16 位,而不是 64 位。
Keep in mind that the JS numbertype is specified as an IEEE754 floating-point value, so it is not guaranteed to be able to hold a 64-bit unsigned value. If you want real 64-bit integer support, you need to use a module to provide it, like bignum. The readme for that has examples of reading and writing values to buffers.
请记住,JSnumber类型被指定为 IEEE754 浮点值,因此不能保证能够保存 64 位无符号值。如果你想要真正的 64 位整数支持,你需要使用一个模块来提供它,比如bignum。该自述文件包含读取和写入缓冲区值的示例。
Floating-point values can only represent values up to 2^53 - 1without losing precision. You can see that in this example using standard JS numbers:
浮点值只能表示2^53 - 1不损失精度的值。您可以在此示例中使用标准 JS 数字看到:
var b = new Buffer([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
var firstHalf = b.readUInt32BE(0); // 4294967295
var secondHalf = b.readUInt32BE(4); // 4294967295
var val = firstHalf * 0x100000000 + secondHalf; // 18446744073709552000
The result of this is 18446744073709552000when the proper value is 18446744073709551615.
这样做的结果是18446744073709552000当正确的值为 时18446744073709551615。
var bignum = require('bignum');
var b = new Buffer([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
var val = bignum.fromBuffer(b);
This results in a BigNumobject with the value 18446744073709551615.
这会产生一个BigNum值为的对象18446744073709551615。
Also, to elaborate on your example code, the value you are using is only 16-bit, and you are trying to work with it using 32-bit functions. You can just do this:
此外,为了详细说明您的示例代码,您使用的值只有 16 位,并且您正在尝试使用 32 位函数使用它。你可以这样做:
var buf = new Buffer(2);
buf.fill(0) // clear all bytes of the buffer
console.log(buf); // outputs <Buffer 00 00>
var int = 0xffff; // as decimal: 65535
// Write it with a standard 16-bit function calls.
buf.writeUInt16BE(int);
// OR write it with 2 8-bit function calls.
buf.writeUInt8(int & 0xff, 0); // right the first part of the int
buf.writeUInt8((int >> 8) & 0xFF, 1); // right the second part of the int
console.log(buf); // outputs <Buffer ff ff>
// Read it as a 16-bit value.
var bufInt = buf.readUInt16BE(0);
console.log(bufInt);
// OR read it as two 8-bit values.
var bufInt = (buf.readUInt8(1) << 8) + buf.readUInt8(0);
回答by meil
// sending time
var sending_time = new Date().getTime();
buffer.writeInt32LE(parseInt(sending_time & 0xffffffff, 10), 16);
buffer.writeInt32LE(parseInt(sending_time / 0xffffffff, 10), 20);
回答by Tracker1
Bitwise operations in JavaScript/EcmaScript will force the number (or any value really) into a 32-bit integer.
JavaScript/EcmaScript 中的按位运算会将数字(或任何真正的值)强制转换为 32 位整数。
You reallyneed to use bignumfor larger values if you need certain precision, or dealing with buffers with larger than 32-bit values.
如果您需要一定的精度,或者处理大于 32 位值的缓冲区,您确实需要将bignum用于更大的值。
var bignum = require('bignum');
//max safe integer to big number
var num = bignum(Number.MAX_SAFE_INTEGER.toString());
var buf = num.toBuffer({endian:'big',size:8 /*8-byte / 64-bit*/});
console.log(buf); //
The example above uses Number.MAX_SAFE_INTEGERwhich is Math.pow(2,53)-1. If you need to use larger numbers, they should be accessed as bignum strings... if you can stay within the range of Integers in JS, you can keep them and convert as above.
上面的例子使用Number.MAX_SAFE_INTEGERwhich is Math.pow(2,53)-1。如果你需要使用更大的数字,它们应该作为 bignum 字符串访问......如果你能保持在 JS 中的整数范围内,你可以保留它们并按上述方式转换。
回答by ReklatsMasters
Reading / Writing 64bit values:
读取/写入 64 位值:
const int64 = Date.now() // 1456909977176 (00 00 01 53 36 9a 06 58)
const b = new Buffer(8)
const MAX_UINT32 = 0xFFFFFFFF
// write
const big = ~~(int64 / MAX_UINT32)
const low = (int64 % MAX_UINT32) - big
b.writeUInt32BE(big, 0) // 00 00 01 53 00 00 00 00
b.writeUInt32BE(low, 4) // 00 00 01 53 36 9a 06 58
// read
var time = parseInt(b.toString('hex'), 16)
time == int64 // true
I use this code without any special modules.
我在没有任何特殊模块的情况下使用此代码。
UPDATE
更新
Works only for numbers <= Number.MAX_SAFE_INTEGER
仅适用于数字 <= Number.MAX_SAFE_INTEGER

