2013-07-31 121 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