|
setup diary |
qda=ARGV[0] dat=qda.sub(/\.qda$/i,"_.dat") d=open(qda,"rb"){|f|f.read} n=d[0,16].unpack("n*") c=n[8] # byte size of the last comment n=n[1] # the number of data sz=d[0x200,2*n].unpack("n*") # size of each data tp=d[0x200+2*n,2*n].unpack("n*") # type names=d[0x200+4*n,40*n].unpack("a40"*n).map(&:strip) r=d[(0x200+4*n+40*n)..-1] sz=sz.zip(tp).map{|s,t| a,b="g","" # big endian float a,b="N","Z21" if t==1 # string a,b="G","" if t==2 # big endian 64bit float *data,r=r.unpack(a*s+"n"*s+b*s+"a*") msk=data[s,s] # mask str=data[2*s,s] # string data=data[0,s] # numeric if t==2 # date or time td=r[0,8].unpack("C*")[3] data=data.map{|l|(Time.gm(l>3e9?1904:2000)+l).getutc.strftime("%d-%m-%Y")} if td==0 #date data=data.map{|l|Time.at(l).getutc.strftime("%H:%M:%S")} if td==1 #12:34:56 data=data.map{|l|["%02d"]*2*":"%l.divmod(60)} if td==2 #12:34 end r=r[136..-1] data=str if t==1 data } mx=sz.map(&:size).max sz=sz.map{|l|l.fill(0,l.size...mx)}.transpose open(dat,"w"){|f| f.puts "# "+r.gsub(/\x0d\x0a?/,"\n# ") if r.size>0 f.puts names*", " sz.each{|l|f.puts l*", "} }まず,引数として与えたファイルを読み込むが,2バイト目からdataの数を,14バイト目からがコメントのサイズを表すようなので,それを取り込む.200hバイトから,それぞれのdataの長さがあり,その次に型だと思われるdataがある.その後に,40バイトずつのdataの名前があり,そのあとにdata本体とマスクだと思われるdataと文字列の場合には21バイドずつの文字列があり,その後にはdataの名前と良くわからないdataが合計136バイトあるようだ.ちなみに,それぞれはbig endianである.さらに,日付の表記は日月年の順番で,内部では秒単位の倍精度浮動小数点で表されているようである.時刻も同様である.ただ,文字列のdataの場合に,data本体には何が保存されているかはよく調べなかった.まあ,特定のversionのKaleidaGraphでセーブしたdataしか変換できないかも知れないが,今回の目的は達成したので,良しとしよう.