mihajlovic's blog

わーい

「固定長toCSV」

今日は出勤だったわけですが、基本何かあったときのための待機だったわけで、
rubyの勉強をしていた。


何かやってみようかなと思い、とりあえずファイルのIOから。
逆引きRuby – www.namaraii.com – Index of TAKEUCHI, Hitoshi
を参考にして書いてみた。

class Record
 def initialize(record)
   @record = record
 end
  
 def etc1
   @record[0..32]
 end
  
 def cd
   @record[33..43]
 end
  
 def etc2
   @record[44..80]
 end
  
end

#(0)
foo = File.open("foo.DAT",'w')


# (1)
emp = Array::new

# (2) - (4)
open("bar.DAT") {|file|
 while l = file.gets
   r = Record::new(l)
   emp << {"etc1"=>r.etc1, "cd"=>r.cd, "etc2"=>r.etc2}
 end
}

# コードでソート
emp.sort! {|a, b| a["cd"] <=> b["cd"]}

emp.each {|h|
 foo.puts "ETC1:" + h['etc1']
 foo.puts "コード:" + h['cd']
 foo.puts "ETC2:" + h['etc2']
 foo.puts '-' * 20
}
foo.close

↑33桁目から11桁のコードという項目でsortして、前後の内容を含め表示。
outputをfoo.datというファイルに書くようにしてみた。


次に固定長のデータを下に各項目で区切ってCSVに と思ったが、
単純にするだけでは面白くないので、各レコードの上1桁='S'のものを対象に抽出しつつ、
CSVにするようにしたいくなった。
ただ、これがてこずって。。。
いったん、各レコードの上1桁='S'のものを対象にするだけのものを作ってみた。

lines = fields = 0  #←じつはここいらないんじゃない?
foo = File.open("foo.DAT",'w')


open("bar.DAT") {|file|
 while l = file.gets
if /^S.*/ =~ l then
foo.puts(l)
end
 end
}

正規表現で先頭が'S'ではじまるものだけを対象に抽出するようにしてそれをoutputのファイルに。


で、さらにそのoutputのファイルをCSVにしてみた。

in1_file    =   open("foo.DAT","r")   
out1_file   =   open("bar.DAT","w")  

#各項目のバイト数を指定する。   
fields      =   "1,2,3,4,5,6,7,8,9,10,11,12"    #←ここで各項目の桁数を指定
fields      =   "A"+fields.gsub(/,/,"A")    

while   (in1    =   in1_file.gets)  

#上1桁が"S"のデータを対象にする。
if /^S.*/ =~ in1 then
   out1_file.print in1.unpack(fields).join(",") ,"\n"   
   end

end

in1_file.close  
out1_file.close


切り貼りしながら書いたので、無駄なものとか入ってるだろうというのと、
一般化するように書き直したので、もしかしたらこのままではエラーになるかもしれないが。。。
今日やってみて、それぞれがどんなことをしてるのかなんとなくわかった。
上1桁='S'のものを抜くのもいろいろ試行錯誤した上で書けたので、良かった。
また機会を作って書いていこうと思う。


今回はwebで調べながらだったし、大体ほしい情報は得られたんだけど、
やはり手元に参考にできる本があったほうが良いなぁ。