3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RubyでJava風ストリーム入力

3
Last updated at Posted at 2016-02-26

Ruby では普通コードブロックを用いてファイルにアクセスしますが,複数の処理を一度に行うときにネストしたブロックになり,一見して複雑なコードになります.Javaのようにいくつものイベントストリームをつなげる形で処理すると,興味の無い下位レイヤーのコードを見る必要がなくなります.

また,ストリームオブジェクトのつながりを切り替えるだけで処理が変わるので,メインの処理のコードと,入力の処理に関するコードを分離することができます.そうすると,メインの処理のコードを変えることなく入力を切り替えることができます.

例えば,テキストのcsvを読むときと,gzipされたcsvを読むとき,ブロックベースのコードだとメインの処理をGZipReaderが包むことになるので,圧縮されていないcsvを読む場合とを両方扱おうとしたとき,複雑になってしまいます.ストリームを使えば,file_reader->csv_readerのチェーンを作るか,file_reader -> gzip_reader -> csv_reader のチェーンを作るかの分岐を切り替えるだけですみます.

Javaではむしろこうしたストリームの読み込みがあたりまえですが,Rubyでどうやるのかをまとめている文書を見つけられなかったので,調べた結果を共有します.

■2016-07-26 出力ストリームについても「RubyでJava風ストリーム出力 」に書きました。

準備

以下のファイルを用意しました.

file_path = "abcd.txt"
gzipfile_path = "abcd.txt.gz"

csv_file_path = "abcd.csv"
gzip_csv_file_path = "abcd.csv.gz"

バイト列をjava.io.InputStream風に読み込む

puts "Java 風に  InputStream"
file_input_stream = File.new(file_path)
begin
  while ch = file_input_stream.read(1)
    b_arr = ch.unpack("C*")
    b = b_arr[0]
    puts "0x#{b.to_s(16)}"  
  end
ensure
  file_input_stream.close
end

文字列を java.io.Reader風に読み込む

puts "Java 風に  FileReader"
file_reader = File.new(file_path)
begin
  while ! file_reader.eof?
    ch = file_reader.readchar
    p ch
  end
ensure
  file_reader.close
end

文字列を java.io.BufferedReader風に読み込む

puts "Java 風に  BufferedReader"
file_reader = File.new(file_path)
begin
  while ! file_reader.eof?
    line = file_reader.readline
    puts line
  end
ensure
  file_reader.close
end

CSVを Reader風にストリームを作って読み込む

puts "Java 風に  CSVReader"
require 'csv'
file_reader = File.new(csv_file_path)
csv_reader = CSV.new(file_reader)
begin
  while ! csv_reader.eof?
    columns = csv_reader.readline
    p columns
  end
ensure
  csv_reader.close
end

Gzip を Reader風にストリームを作って読み込む

puts "Java 風に  ストリーム file -> gzip"
require 'zlib'
file_reader = File.new(gzipfile_path)
gzip_reader = Zlib::GzipReader.new(file_reader)
begin
  while ! gzip_reader.eof?
    line = gzip_reader.readline
    puts line
  end
ensure
  gzip_reader.close
end

Gzip された CSVをReader風にストリームを作って読み込む

puts "Java 風に  ストリーム file -> gzip -> csv"
require 'zlib'
require 'csv'
file_reader = File.new(gzip_csv_file_path)
gzip_reader = Zlib::GzipReader.new(file_reader)
csv_reader = CSV.new(gzip_reader)
begin
  while ! csv_reader.eof?
    columns = csv_reader.readline
    p columns
  end
ensure
  csv_reader.close
end
3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?