Javascript 将javascript整数转换为字节数组并返回

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8482309/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 06:10:02  来源:igfitidea点击:

Converting javascript Integer to byte array and back

javascript

提问by Ben Reeves

function intFromBytes( x ){
    var val = 0;
    for (var i = 0; i < x.length; ++i) {        
        val += x[i];        
        if (i < x.length-1) {
            val = val << 8;
        }
    }
    return val;
}

function getInt64Bytes( x ){
    var bytes = [];
    var i = 8;
    do {
    bytes[--i] = x & (255);
    x = x>>8;
    } while ( i )
    return bytes;
}

I am trying to convert a javascript number to a byte array and then back to a number. However the above functions produce incorrect output with a very large number.

我正在尝试将一个 javascript 数字转换为一个字节数组,然后再转换回一个数字。然而,上述函数会产生非常大的错误输出。

var array = getInt64Bytes(23423423);    
var value = intFromBytes(array);

console.log(value); //Prints 23423423 - correct

var array = getInt64Bytes(45035996273704);  
var value = intFromBytes(array);

console.log(value); //Prints -1030792152 - incorrect

It is my understanding that javascript floats are 53bits so it shouldn't be overflowing? alert(Math.pow(2,53))works fine.

我的理解是 javascript 浮点数是53位,所以它不应该溢出?alert(Math.pow(2,53))工作正常。

采纳答案by Crozin

In JavaScript bit shifts (>>, <<) are always performed on signed, 32-bits integers. This leads to range overflow for large numbers.

在 JavaScript 中,位移 ( >>, <<) 总是在有符号的 32 位整数上执行。这会导致大量数字的范围溢出。

回答by Younes

Using the hint provided by Susanoh13, here are the two functions that allow conversion of number from/to ByteArray:

使用 Susanoh13 提供的提示,这里有两个允许数字从/到 ByteArray 的转换的函数:

longToByteArray = function(/*long*/long) {
    // we want to represent the input as a 8-bytes array
    var byteArray = [0, 0, 0, 0, 0, 0, 0, 0];

    for ( var index = 0; index < byteArray.length; index ++ ) {
        var byte = long & 0xff;
        byteArray [ index ] = byte;
        long = (long - byte) / 256 ;
    }

    return byteArray;
};

byteArrayToLong = function(/*byte[]*/byteArray) {
    var value = 0;
    for ( var i = byteArray.length - 1; i >= 0; i--) {
        value = (value * 256) + byteArray[i];
    }

    return value;
};

回答by Kamil Kie?czewski

try (**is power operator, <<and >>>are bit-shift operators) - intFromBytesworks only for arrays generated from positive integers

try(**幂运算符<<并且>>>位移运算符) -intFromBytes仅适用于从正整数生成的数组

function getInt64Bytes(x) {
  let y= Math.floor(x/2**32);
  return [y,(y<<8),(y<<16),(y<<24), x,(x<<8),(x<<16),(x<<24)].map(z=> z>>>24)
}

function intFromBytes(byteArr) {
    return byteArr.reduce((a,c,i)=> a+c*2**(56-i*8),0)
}

function getInt64Bytes(x) {
  let y= Math.floor(x/2**32);
  return [y,(y<<8),(y<<16),(y<<24), x,(x<<8),(x<<16),(x<<24)].map(z=> z>>>24)
}

function intFromBytes(byteArr) {
    return byteArr.reduce((a,c,i)=> a+c*2**(56-i*8),0)
}


// TEST

let n = 40*2**40 + 245*2**32 + 194*2**24 + 143*2**16 + 92*2**8 + 40;
let b = getInt64Bytes(n);
let i = intFromBytes(b);

console.log(`number      : ${n}`);
console.log(`int to bytes: [${b}]`);
console.log(`bytes to int: ${i}`);

回答by StoicJester

Doing a bit shift is the same as multiplying by 2^(# of bits+1), so instead of shifting the bits val = val<<8, you can just do val = val*256. See if that works.

进行位移位与乘以 2^(# of bits+1) 相同,因此val = val<<8您只需执行val = val*256. 看看这是否有效。

回答by SET

Brainfwor-style Lodash version. Just 4 lulz! don't use it!

Brainfwor 风格的 Lodash 版本。只需 4 个 lulz!不要使用它!

const uintToArray = (uint, size) => _.chunk(_.padStart(uint, size*2,  0).split(''), 2).map((a)=>parseInt(a[0]+a[1]))

回答by Valery Rode

<html>
<head>
    <meta charset="utf-8">
    <title>Uint32_To_Byte_Array</title>
    <script>
    function body_Add(Msg)
    {
        document.body.innerHTML = document.body.innerHTML + Msg;
    }
    class Byte 
    {
        constructor(Value) 
        {
            this.Number = new Uint8Array(1);
            this.Number[0] = Value;
        }
        get Get() 
        {
            return this.Number[0];
        }
        set Set(newValue) 
        {
            this.Number[0] = newValue;
        }
    };
    class Uint32
    {
        constructor(Value) 
        {
            this.Number = new Uint32Array(1);
            this.Number[0] = Value;
        }
        get Get() 
        {
            return this.Number[0];
        }
        set Set(newValue) 
        {
            this.Number[0] = newValue;
        }
    };
    var Conversion =
    {
        Uint32_To_Byte_Array: function(Source_Num)
        {
            var Uint32_Num = new Uint32(Source_Num);
            var Byte_Num = new Byte(0);
            var Byte_Arr = new Uint8Array(4);
            for (var i = 0; i < 4; i++)
            {
                if (Source_Num > 255)
                {
                    Uint32_Num.Set = Source_Num / 256;
                    Byte_Num.Set = Source_Num - Uint32_Num.Get * 256;
                }
                else
                {
                    Byte_Num.Set = Uint32_Num.Get;
                    Uint32_Num.Set = 0;
                }
                Byte_Arr[i] = Byte_Num.Get;
                Source_Num = Uint32_Num.Get;
            }
            return(Byte_Arr);
        },
        Byte_Array_To_Uint32: function(Source_Byte_Array, Start_Position)
        {
            var Uint32_Num = new Uint32(0);
            var Multiplier = 1;
            for (let i = 0; i < 4; i++)
            {
                Uint32_Num.Set = Uint32_Num.Get + Source_Byte_Array[Start_Position + i] * Multiplier;
                Multiplier = Multiplier * 256;
            }
            return (Uint32_Num.Get);
        }
    };
    function Load_Page()
    {
        var Numbers = [0,1,257,4294967295];
        Numbers.forEach(Convert);
        function Convert(Item, Index)
        {
            var Uint32_Number = Item;
            var Byte_Array = Conversion.Uint32_To_Byte_Array(Uint32_Number);
            var Uint32_Number_Restored = Conversion.Byte_Array_To_Uint32(Byte_Array, 0);
            body_Add("Conversion: Source number: " + Uint32_Number.toString() + ", Byte array: " + Byte_Array.toString() + ", Restored number: " + Uint32_Number_Restored.toString() + "<br>");
        };
    };
    </script>
</head>
<body onload="Load_Page()"> 
</body>

回答by Chris Moschini

If you happen to be on Node.js, Bufferis the correct way to handle any byte array/stream in Javascript/Typescript:

如果您碰巧使用 Node.js,Buffer那么在 Javascript/Typescript 中处理任何字节数组/流的正确方法是:

https://nodejs.org/api/buffer.html

https://nodejs.org/api/buffer.html

Although the docs are more comprehensive, Stack Overflow recommends code snippets here in case that link 404s, so here are a couple of the most important code examples in that doc:

尽管文档更全面,但 Stack Overflow 建议在此处使用代码片段以防链接 404,因此这里是该文档中最重要的几个代码示例:

// Creates a Buffer containing the UTF-8-encoded bytes for the string 'tést':
// [0x74, 0xc3, 0xa9, 0x73, 0x74] (in hexadecimal notation)
// [116, 195, 169, 115, 116] (in decimal notation)
const buf6 = Buffer.from('tést');

// Creates a Buffer containing the bytes [1, 2, 3].
const buf4 = Buffer.from([1, 2, 3]);