【问题标题】:Convert byte array to numbers in JavaScript在 JavaScript 中将字节数组转换为数字
【发布时间】:2011-12-02 18:46:38
【问题描述】:

我有 JavaScript 代码,可以从网络服务中检索数值向量。原始数据是一个双精度数组,它被转换为字节数组,然后进行 base64 编码。我在 JavaScript 中从 base64 解码,但是我不知道如何将结果字节转换为数字数组。

【问题讨论】:

  • 我不确定您的数据是什么样的,但您可以使用 .split("delimiterCharacter") 从分隔数据创建一个数组
  • 呃,将数据加倍为字节序列 - 我认为,您必须手动实现。 In this question我找到了一个将double转换为字节的算法,也许你可以反转它。
  • 你能提供一些示例数据吗?
  • @alecgorge 以下是在 base64 解码后使用 console.log() 打印的内容: l²@ù±@*±@±@Ó°@¾¯@â®@&®@ @@ ©@ ©@¶¨@Æ©@À§@V©@ä§@²¨@¬§@ʧ@Ч@§@²©@Ú¨@¥@©@¶§@À¥@¦ @L¦@è¦@¦@ª¦@¦@§@§@(§@N¨@~¨@¨@©@ª@¨@l«@Vª@îª@¦«@¨@D«@ v«@4«@à«@ª@«@@r@þ¬@,®@b®@Ư@¯@Ø®@Ì®@D°@n°@,°@Ø®@æ¬ @ȯ@1°@|°@h°@h°@v°@z¯@¾°@r°@̯@·°@Я@ü¯@â¯@¯@¯@z®@ö®@¬@j¬@°©@>«@d©@¨@¨@H¥@À¤@î¤@¤@ ¡@Æ¢@Ê @Ø@* @T @@@@Ü @Ä@@0@@Þ @¡@¸¢@î¢@¢@¨£@ø£@ú¢@¤@¤@£ @ä¢@¥@Ò¥@¤@J¥@&¦@¨¦@
  • @Abiel 这有点笨拙。 gist 中的 base64 编码数据怎么样?

标签: javascript


【解决方案1】:

这是我能想到的唯一方法。

function bytesToDouble(str,start) {
    start *= 8;
    var data = [str.charCodeAt(start+7),
                str.charCodeAt(start+6),
                str.charCodeAt(start+5),
                str.charCodeAt(start+4),
                str.charCodeAt(start+3),
                str.charCodeAt(start+2),
                str.charCodeAt(start+1),
                str.charCodeAt(start+0)];

    var sign = (data[0] & 1<<7)>>7;

    var exponent = (((data[0] & 127) << 4) | (data[1]&(15<<4))>>4);

    if(exponent == 0) return 0;
    if(exponent == 0x7ff) return (sign) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;

    var mul = Math.pow(2,exponent - 1023 - 52);
    var mantissa = data[7]+
        data[6]*Math.pow(2,8*1)+
        data[5]*Math.pow(2,8*2)+
        data[4]*Math.pow(2,8*3)+
        data[3]*Math.pow(2,8*4)+
        data[2]*Math.pow(2,8*5)+
        (data[1]&15)*Math.pow(2,8*6)+
        Math.pow(2,52);

    return Math.pow(-1,sign)*mantissa*mul;
}

var data = atob("AAAAAABsskAAAAAAAPmxQAAAAAAAKrF");

alert(bytesToDouble(data,0)); // 4716.0
alert(bytesToDouble(data,1)); // 4601.0

这应该会推动您朝着正确的方向前进,尽管我花了一段时间才记住如何处理 doubles。

需要注意的一个重要警告:

这依赖于 atob 进行 base64 解码,但并非所有地方都支持,除此之外,这可能不是一个好主意。您真正想要做的是将 base64 编码的字符串展开为一个数字数组(字节将是最容易使用的,尽管不是地球上最有效的东西)。原因是当atob 施展魔法时,它返回一个字符串,这远非理想。根据其映射到的代码点的编码(尤其是对于 128 到 255 之间的代码点),生成的 .charCodeAt() 可能不会返回您期望的结果。

而且可能存在一些准确性问题,因为毕竟我是使用双精度数来计算双精度数,但我认为它可能没问题。

Base64 使用起来相当简单,所以你应该能够弄清楚这部分。

如果您确实切换到数组(而不是现在的 str 字符串),那么您显然会删除 .charCodeAt() 引用并直接获取您想要的索引。

有一个functioning fiddle here

【讨论】:

  • 谢谢。这对我有用。我正在使用其他一些代码来解码 base64,所以不太关心atob 问题。我会留意准确性问题,但总的来说我的数据不需要特别高的精度,所以应该没问题。
【解决方案2】:

我假设我们已经在 web 服务 (c#) 中使用了这个函数来将双数组数据编码为字符串:

//Input: [552.4, 539.8]
//Output: IOz0gCAsscA=

private string ConvertToSerializableString(double[] input)
{
  byte[] data = new byte[input.Length * 4];
  for (int i = 0; i < input.Length; i++)
  {
    int source = (int)(input[i] * 1E6);    
    int dataIndex = i * 4;
    data[dataIndex] = (byte)((source >> 24) & 0xFF);
    data[dataIndex + 1] = (byte)((source >> 16) & 0xFF);
    data[dataIndex + 2] = (byte)((source >> 8) & 0xFF);
    data[dataIndex + 3] = (byte)(source & 0xFF);
  }

  return Convert.ToBase64String(data);          
}

然后我们可以使用下面的客户端脚本(javascript)对其进行解码:

var base64EncodedDoubleArrayData = "IOz0gCAsscA=";
var byteData = window.atob(base64EncodedDoubleArrayData);                

var doubleArray = [];
for (var iColumn = 0; iColumn < byteData.length; iColumn = iColumn + 4) 
{
   var item = (byteData.charCodeAt(iColumn) << 24) + (byteData.charCodeAt(iColumn + 1) << 16) + (byteData.charCodeAt(iColumn + 2) << 8) + byteData.charCodeAt(iColumn + 3);   
   var doubleResult = parseFloat(item/1e6);
   doubleArray.push(doubleResult);
}  

//it should return something like doubleArray = [552.4, 539.8]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-08
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    相关资源
    最近更新 更多