【问题标题】:How to convert binary into data?如何将二进制转换为数据?
【发布时间】:2014-07-12 03:28:38
【问题描述】:

我一直在尝试转换从 R 中的 API 获得的二进制数据,但它无法正确解析和转换值。

这是一个二进制示例:

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

但它没有生成上面列出的目标结果。

【问题讨论】:

    标签: r import binary-data


    【解决方案1】:

    好的。我想我已经弄清楚了,除了日期/时间。首先,这是你的二进制数据

    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 与“字符”一起使用时,它会读取C 风格的字符串,因此它包含以下x00readChar 不这样做。我还必须小心指定值的字节顺序,因为“大”不是我系统的默认设置(我在 Mac 上运行)。

    【讨论】:

    • @thelatemail 对。如果您使用数组索引,则没有内部指针可以跟踪您所在的位置,因此您可以四处跳转。但是该值的宽度取决于先前的值。所以应该是readBin(rr[7:(7+strwidth-1)],"character") 其中strwidth 是前一个整数。
    • 一切都适用于我粘贴的二进制字符串;但是,我在让 r 遍历整个二进制文件时遇到了另一个问题。当我将代码放入 for 循环时,它在第 247 行停止,我不确定原因。 readBin 和 file("text.bin","rb") 是否有某种限制?
    • @BryanNice “停止”是什么意思?它会抛出错误吗?您如何跟踪二进制文件中的行?知道何时完成的循环的条件是什么?
    • @MrFlick 我使用的条数是我的迭代器限制。不过,我发现了这个问题。我使用 readBin 直接从 API 下载数据并将其保存到文件中。我将其更改为使用 download.file() 方法并解决了该问题。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-02
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 2015-02-14
    • 1970-01-01
    相关资源
    最近更新 更多