如何将二进制转换为数据?

5

我一直在尝试将我从API中获取的二进制数据转换为R,但它没有正确地解析和转换值。

以下是二进制数据的样本:

00 00 00 01 00 04 53 42 55 58 00 00 00 25 c8 42 9b cc cd 42 9c 8a 3d 42 9b b8 52 42 9c 23 d7 44 bd 5e 14 00 00 01 43 53 5c 62 40

结果应该是:
SBUX    77.9    78.27   77.86   78.07   1153261076  1/2/2014 9:30

使用正确的数据类型和大小的示例代码

readBin(file2read[1:4],integer(),n=1, size=4) #Symbol Count
readBin(file2read[5:6],integer(),n=1,size=2) #Symbol length
readBin(file2read[7:10],character(),n=4) #Sympbol = SBUX
readBin(file2read[11],integer(),n=1,size=1) #Error code
readBin(file2read[12:15],integer(),n=4) #Bar Count
readBin(file2read[16:19],double(),n=4,size=4) #close
readBin(file2read[20:23],double(),n=1,size=4) #high
readBin(file2read[24:27],double(),n=1,size=4) #low
readBin(file2read[28:31],double(),n=1,size=4) #open
readBin(file2read[32:36],double(),n=1,size=4) #volume
readBin(file2read[37:44],character(),n=1,size=8) #timestamp

但是它没有产生上面列出的目标结果。
1个回答

3

好的,我认为我已经想通了一切,但是日期/时间还需要处理。首先,这里是您的二进制数据。

rr<-as.raw(c(0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x53, 0x42, 0x55, 
0x58, 0x00, 0x00, 0x00, 0x25, 0xc8, 0x42, 0x9b, 0xcc, 0xcd, 0x42, 
0x9c, 0x8a, 0x3d, 0x42, 0x9b, 0xb8, 0x52, 0x42, 0x9c, 0x23, 0xd7, 
0x44, 0xbd, 0x5e, 0x14, 0x00, 0x00, 0x01, 0x43, 0x53, 0x5c, 0x62, 
0x40))

我只是要把数据写入一个文件,以便用readBin更容易地读取它。(而且因为符号长度可变,所以在它后面的值的索引可能不同;文件连接将跟踪下一个字节。) 在这里,我将其写入磁盘,然后打开它。

writeBin(rr,"test.bin")
zz <- file("test.bin", "rb")

现在我读取数值

(nrec<-readBin(zz, "integer", size=4, endian="big"))
(charsize<-readBin(zz, "integer", size=2, signed=F, endian="big"))
(symbol<-readChar(zz, charsize))
(err<-readBin(zz, "integer", size=1, signed=F))
(bcount<-readBin(zz, "integer",size=4, endian="big"))
(sclose<-readBin(zz, "double",size=4, endian="big"))
(shigh<-readBin(zz, "double",size=4, endian="big"))
(slow<-readBin(zz, "double",size=4, endian="big"))
(sopen<-readBin(zz, "double",size=4, endian="big"))
(svol<-readBin(zz, "integer",size=4, endian="big"))
(sdate<-readBin(zz, "integer",size=4, n=2, endian="big"))
#done
close(zz)

因此,barcount变量没有在您的输出中,但它似乎有一个值为9672。现在日期有点棘手。它被存储为64位整数。而且R似乎不喜欢使用readBin读取这些(至少在我的机器上),所以我将其读入为两个整数。您可以使用以下方法将其转换为日期:

 as.POSIXct(sdate[1]*2^32/1000 + sdate[2]/1000, origin="1970-01-01")
 # [1] "2014-01-02 09:30:00 EST"

这看起来可以正确提取数据。一个主要的陷阱是使用 readChar 读取字符,因为当你使用 readBin 读取 "character" 时,它会读取 C 风格的字符串,所以它包括后面的 x00。而 readChar 不会这样做。我还需要小心地指定数值的字节序,因为“big”不是我的系统的默认值(我在 Mac 上运行)。


@thelatemail 对的。如果使用数组索引,就没有内部指针来跟踪您所在的位置,因此您可以随意跳转。但是该值的宽度取决于先前的值。因此,应为readBin(rr[7:(7+strwidth-1)],"character"),其中strwidth是先前的整数。 - MrFlick
所有二进制字符串都能正常运转,但是我在迭代整个二进制文件时遇到了另一个问题。当我将代码放入for循环中时,它会停止在第247行,而我不确定原因。readBin和file("text.bin","rb")是否有某种限制? - Bryan Nice
@BryanNice,“stops”是什么意思?它会抛出错误吗?你是如何在二进制文件中跟踪行的?你的循环条件是什么,以知道何时完成? - MrFlick
@MrFlick 我使用了条形计数作为我的迭代器限制。然而,我找到了问题所在。我之前是直接使用readBin从API下载数据并保存到文件中。现在我改用download.file()方法,问题得以解决。感谢您的帮助。 - Bryan Nice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接