ファイルの出力のとき、CSV, GZIP, File書き出し、といったように複数の処理を経ることがあります。これらを個別に行うとメモリを大量に消費しますが、ストリーム処理にすれば少しずつ処理されるので省メモリで済みます。また、処理がオブジェクトでカプセル化されるので、インスタンスを取り回したり、さらにラップしたりできます。
欠点は1パスで出力するので途中で戻って最初の方の内容を書き直したりできない点と、begin rescue end のブロックが増える点です。
Rubyではほとんどのサンプルコードがブロックで書かれていますが、実はJavaのようにストリーム処理が可能です。この記事では出力ストリームをJava風に書いてみます。
■ちなみに入力ストリームについては
RubyでJava風ストリーム入力
に書いていますのでご参考ください。
require 'tempfile'
require 'csv'
require 'zlib'
file_path = Tempfile.new().path
table = [
['a', 'b'],
['c', 'd']
]
#######################
puts "Java 風に FileWriter"
writer = File.new(file_path, 'w')
begin
table.each do |row|
row.each do |elem|
writer.write(elem)
writer.write(',')
end
writer.write($/)
end
ensure
writer.close
end
puts File.open(file_path).read
#######################
puts "Java 風に GzipWriter -> Writer"
writer = File.new(file_path, 'w')
writer = Zlib::GzipWriter.new(writer)
begin
table.each do |row|
row.each do |elem|
writer.write(elem)
writer.write(',')
end
writer.write($/)
end
ensure
writer.close
end
puts Zlib::GzipReader.new(File.open(file_path)).read
#######################
puts "Java 風に CSVWriter -> Writer"
writer = File.new(file_path, 'w')
csv_writer = CSV.new(writer, {col_sep: ',', row_sep: $/});
begin
table.each do |row|
csv_writer.puts(row)
end
ensure
csv_writer.close
end
puts File.open(file_path).read
#######################
puts "Java 風に CSVWriter -> GzipWriter -> Writer"
writer = File.new(file_path, 'w')
writer = Zlib::GzipWriter.new(writer)
csv_writer = CSV.new(writer, {col_sep: ',', row_sep: $/});
begin
table.each do |row|
csv_writer.puts(row)
end
ensure
csv_writer.close
end
puts Zlib::GzipReader.new(File.open(file_path)).read