2013-07-31 89 views
2

我想从使用R的混合数据文件(ascii和binary)中读取二进制数据,数据文件是以伪xml格式构造的。我的想法是使用扫描功能,阅读具体的行,然后将二进制转换为数值,但我似乎无法在R中做到这一点。我有一个Python脚本来做到这一点,但我想做R中的作业,python脚本如下。数据文件中的二进制部分由开始和结束标记以及。从混合数据文件中提取二进制数据

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

BinData元素的数据被写为二进制字节数组。每个 二进制数组的8个字节表示一个双精度浮点值 。因此二进制数组的大小是 NumberOfPoints * 8个字节。对于二维数组,数据布局 遵循由SafeArrays使用的行主窗体。这意味着移动到 下一个数组元素递增最后一个索引。例如,如果以这样的一维二进制字节数组形式写入二维数组(例如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) 
+0

如果二进制数据碰巧随机包含终止字符串'',会发生什么? - XML文件中的二进制数据应该是base64编码或类似的。 – Roddy

回答

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)])) 
+0

这真是太好了,太简单了。谢谢。 – user2638366