在Apps脚本中解析字节数组

时间:2013-07-12 15:19:11

标签: javascript google-apps-script

我从股票API获得以下数据:

  

0,0,0,1,0,4,71,79,79,71,0,0,0,0,4,69,93,-17,-65,-67,82,68, 95,5,31,> 68,93,64,0,68,93,-17,-65,-67,-17,-65,-67,70,-17,-65,-67,52 ,-17,-65,-67,> 0,0,1,63,-17,-65,-67,99,30,0,68,92,-17,-65,-67,-17 ,-65,-67,68,94,-17,> -65,-67,0,68,91,81,72,68,94,-17,-65,-67,-17,-65 ,-67,70,-17,-65,-67,-17,> -65,-67,87,0,0,1,63,-17,-65,-67,-17,-65 ,-67,122,0,68,93,-17,-65,-67,> -17,-65,-67,68,94,74,-17,-65,-67,68,91 ,-17,-65,-67,0,68,91,-17,-65,-67,> 70,34,107,10,0,0,1,63,-17,-65, - 67,-17,-65,-67,-17,-65,-67,0,68,95,95,> 92,68,95,-17,-65,-67,61,68,93 ,-17,-65,-67,-17,-65,-67,68,94,-17,-65,> -67,0,70,127,-17,-65,-67,0 ,0,1,63,-17,-65,-67,-17,-65,-67

这是下面的代码成功完成的二进制读取,返回数组{error = 0.0,symbol = GOOG,count = 1,bars = 4,length = 4,bar = []}:

  

0,0,0,1,0,4,71,79,79,71,0,0,0,0,4

从现在开始,我正在努力:

  <68>,93,-17,-65,-67,82,68,95,5,31,> 68,93,64,0,68,93,-17,-65,-67, - 17,-65,&gt; -67,70,-17,-65,-67,52,-17,-65,-67,&gt; 0,0,1,63,-17,-65,-67 ,99,30,0,68,92,&gt; -17,-65,-67,-17,-65,-67,68,94,-17,&gt; -65,-67,0,68, 91,81,72,68,94,-17,-65,&gt; -67,-17,-65,-67,70,-17,-65,-67,-17,&gt; -65, - 67,87,0,0,1,63,-17,-65,-67,&gt; -17,-65,-67,122,0,68,93,-17,-65,-67,&gt; ; -17,-65,-67,68,94,74,-17,-65,-67,&gt; 68,91,-17,-65,-67,0,68,91,-17, - 65,-67,&gt; 70,34,107,10,0,0,1,63,-17,-65,&gt; -67,-17,-65,-67,-17,-65, - 67,0,68,95,95,&gt; 92,68,95,-17,-65,-67,61,68,93,&gt; -17,-65,-67,-17,-65, -67,68,94,-17,-65,&gt; -67,0,70,127,-17,-65,-67,0,0,1,&gt; 63,-17,-65, - 67,-17,-65,-67

以上是代码的四个“条形”,包括close,high,low,open,volume和timestmap。除了Volume之外,所有这些都是4字节浮点数,长度为8,长度为8.长度由API描述为8位字节。

我没有解析代码的第一位问题(虽然它可能不完美)。我和其他人有问题。从API网站,这是数据的结构:

字段类型长度(8位字节)说明


Symbol Count Integer 4要返回数据的符号数。后续部分重复多次

重复符号数据

符号长度短2符号字段的长度

符号字符串变量返回历史数据的符号

错误代码字节1 0 =正常,1 =错误

错误长度短2仅在错误代码= 1时返回。错误字符串的长度

错误文本字符串变量仅在错误代码= 1时返回。描述错误的字符串

Bar Count Integer 4#图表栏;仅当错误代码= 0

重复价格数据

关闭Float 4 高浮动4 低浮动4 打开Float 4 容量浮动4(100) timestamp从1970年1月1日00:00:00 UTC开始的长8小时(以毫秒为单位)

重复价格数据

终结符字节2 0xFF,0XFF

重复符号数据的结束 PriceHistory响应采用二进制格式,由符号,图表数量

表示

重复符号数据的结束

我能够提取计数,长度,符号,错误代码和条形数。但它正在解析我遇到的问题。我没有得到任何数据,而是像D] R9那样的胡言乱语。

如果你想知道我到目前为止有多糟糕,可以使用代码:):http://pastebin.com/5eq9XPjT

  for (i=0;i<=dataArray.length;i++) {
if (i<=5) {
  symbolDetails['count'] = Utilities.newBlob(dataArray[0] + dataArray[1] + dataArray[2] + dataArray[3]).getDataAsString(); //Symbol count
  symbolDetails['length'] = Utilities.newBlob(dataArray[4] + dataArray[5]).getDataAsString(); // Length of record
  i=5; // jump ahead
} else if (i>5 && i<6+Number(symbolDetails['length'])) {
  for (j=0;j<Number(symbolDetails['length']);j++) {
    symbolDetails['symbol'][j] = dataArray[i];
    i++
  }
  i = 10;
  Logger.log(symbolDetails['symbol']);
  symbolDetails['symbol'] = Utilities.newBlob(symbolDetails['symbol']).getDataAsString();
  // partTwo is the sequence of data after the symbol. As symbol can be of varying length, this will help us know where we are.
  var partTwo = 5 + Number(symbolDetails['length']);
} else {
  // Get Error Code
  if (i == partTwo) {
    symbolDetails['error'] = Utilities.newBlob(dataArray[i]).getDataAsString();
  } else if (i>= Number(partTwo + 1) && i<=Number(partTwo+5)) {
    // Get Bar Count
    for (j=0;j<4;j++) {
      symbolDetails['bars'] =+ dataArray[i];
      i++;
    }
    symbolDetails['bars'] = Utilities.newBlob(symbolDetails['bars']).getDataAsString();
  }
}

}

希望有人可以帮助解决这个问题。非常感谢你。

1 个答案:

答案 0 :(得分:0)

我不完全确定您的数据,但我会假设它是一系列带符号的8位值。

首先让我们将其视为十六进制,因为这比签名值更容易处理:

00 00 00 01 00 04 47 4f 4f 47 00 00 00 00 04 44 5d ef bf bd
52 44 5f 05 1f 44 5d 40 00 44 5d ef bf bd ef bf bd 46 ef bf
bd 34 ef bf bd 00 00 01 3f ef bf bd 63 1e 00 44 5c ef bf bd
ef bf bd 44 5e ef bf bd 00 44 5b 51 48 44 5e ef bf bd ef bf
bd 46 ef bf bd ef bf bd 57 00 00 01 3f ef bf bd ef bf bd 7a
00 44 5d ef bf bd ef bf bd 44 5e 4a ef bf bd 44 5b ef bf bd
00 44 5b ef bf bd 46 22 6b 0a 00 00 01 3f ef bf bd ef bf bd
ef bf bd 00 44 5f 5f 5c 44 5f ef bf bd 3d 44 5d ef bf bd ef
bf bd 44 5e ef bf bd 00 46 7f ef bf bd 00 00 01 3f ef bf bd

让我们按顺序进行:

# Symbol Count = 1
00 00 00 01

# Symbol Length = 4
00 04

# Symbol = 'GOOG'
47 4f 4f 47

# Error Code = 0
00

# Error Length & Error Text are not present since Error Code == 0

# Bar Count = 4
00 00 00 04

现在问题区域。下一个值是浮点数。特别是它是一个小端格式的浮点数。 This question可以帮助将字节转换为浮点数。请注意,您的字节顺序与问题中的字节顺序不同,因此您需要反转字节。

# Close = $887.74
44 5d ef bf

这是一些解码此值并将其打印出来的Javascript代码。它使用先前引用的SO答案的Bytes2Float32函数。

function Bytes2Float32(bytes)
{
    var sign = (bytes & 0x80000000) ? -1 : 1;
    var exponent = ((bytes >> 23) & 0xFF) - 127;
    var significand = (bytes & ~(-1 << 23));

    if (exponent == 128) 
        return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);

    if (exponent == -127) {
        if (significand == 0) return sign * 0.0;
        exponent = -126;
        significand /= (1 << 22);
    } else significand = (significand | (1 << 23)) / (1 << 23);

    return sign * significand * Math.pow(2, exponent);
}

var bytes = new Array(0x44, 0x5D, 0xEF, 0xBF);
var asInt = (bytes[3] & 0xFF) 
          | ((bytes[2] & 0xFF) << 8)  
          | ((bytes[1] & 0xFF) << 16) 
          | ((bytes[0] & 0xFF) << 24);

write("As Int: " + asInt + "\n");
var asFloat = Bytes2Float32(asInt);
write("Closing Price: " + asFloat);

实际上这打印了887.74603,这听起来像是收盘价。

您将对高低,开放和音量值执行相同的操作(请记住,根据API规范,多个音量为100)。对于时间戳,它是一个很长的,所以将这8个字节转换为long并找到正确的Date API将值转换为Date对象。