从混合数据文件中提取二进制数据

时间:2013-07-31 14:33:52

标签: r

我正在尝试使用R从混合数据文件(ascii和binary)读取二进制数据,数据文件以伪xml格式构造。我的想法是使用扫描功能,读取特定的行,然后将二进制转换为数值,但我似乎无法在R中这样做。我有一个python脚本,这样做,但我想做在R中的工作,python脚本在下面。数据文件中的二进制部分由开始和结束标记括起来。

数据文件是包含光谱数据的专有格式,下面包含指向示例数据文件的链接。引用用户手册:

  

BinData元素的数据被写为二进制字节数组。每   二进制数组的8个字节表示一个双精度   浮点值。因此二进制数组的大小是   NumberOfPoints * 8个字节。对于二维数组,数据布局   遵循SafeArrays使用的行主格式。这意味着搬到   next数组元素递增最后一个索引。例如,如果是   二维阵列(例如Data(i,j))被写入其中   一维二进制字节数组形式,移动到下一个8字节   二进制数组的元素递增原始的最后一个索引   二维阵列(即Data(i,j + 1))。在最后一个元素之后   二进制数组回车和换行的组合   写入字符(ANSI字符13和10)。

提前感谢您的任何建议!

链接到示例数据文件:

https://docs.google.com/file/d/0B5F27d7b1eMfQWg0QVRHUWUwdk0/edit?usp=sharing

Python脚本:

import sys, struct, csv
f=open(sys.argv[1], 'rb')
#
t = f.read()
i = t.find("<BinData>") + len("<BinData>") + 2 # add \r\n line end
header = t[:i]
#
t = t[i:]
i = t.find("\r\n</BinData>")
bin = t[:i]
#
doubles=[]
for i in range(len(bin)/8):
  doubles.append(struct.unpack('d', bin[i*8:(i+1)*8])[0])
#
footer = t[i+2:]
#
myfile = open("output.csv", 'wb')
wr = csv.writer(myfile, quoting=csv.QUOTE_ALL)
wr.writerow(doubles)

1 个答案:

答案 0 :(得分:2)

我写了pack package以使这更容易。您仍然需要搜索二进制数据的开头/结尾。

b <- readBin("120713b01.ols", "raw", 4000)
# raw version of the start of the BinData tag
beg.raw <- charToRaw("<BinData>\r\n")
# only take first match, in case binary data randomly contains "<BinData>\r\n"
beg.loc <- grepRaw(beg.raw,b,fixed=TRUE)[1] + length(beg.raw)
# convert header to text
header <- scan(text=rawToChar(b[1:beg.loc]),what="",sep="\n")
# search for "<Number of Points"> tags and calculate total number of points
numPts <- prod(as.numeric(header[grep("<Number of Points>",header)+1]))

library(pack)
Data <- unlist(unpack(rep("d", numPts), b[beg.loc:length(b)]))