工藤探偵事務所

Resarch and Investigation

ルビー3分クッキング 第十三回「ひらけゴマ!」の巻

kudo-shunsaku2008-04-26




3分間で覚える Ruby のトピックスです。
でも、本家同様に実際には10分程度掛かります。

大事なのは小さな積み重ねと継続する才能ですね。
一番の怠け者の俺が言うのも変ですけどね。

第十三回は、「ひらけゴマ!」の巻です。

今回は実際にファイルを触ってみたいと想います。

Ruby では、最初から使える「組み込みライブラリ」や「添付ライブラリ」などが豊富に揃っています。特にファイルを操作するライブラリは充実の品揃えで用意されています。

通常のプログラミングでもファイルを操作することは頻繁に行われることでしょうから、これらを覚えておいて損はないと想います。

特に私は先般、Ruby で初めてまともなプログラムを書かなければいけない羽目になりまして、そのプログラムというのはデータ変換(コンバージョン)の操作を処理するためのコマンドライン・ツールを作る、というお仕事でした。ですから Ruby の勉強を兼ねてこのプログラムをシコシコと書いたので御座います。

そのプログラムの処理の中核はファイルの操作であり、実際に私もファイル周りのライブラリを色々使わせて頂きました。Rubyのライブラリは非常に便利だなぁ、としみじみと実感した次第です。

今回はまずそのさわりをご紹介したいと想います。

では早速、ファイルの操作を行ってみることにしましょう。
まずはファイルの内容を読み込んで標準出力に印字させましょう。

まずは読み込むファイルとして "beefstew_recipe.txt" を用意します。

『ビーフシチューのレシピ』

材料 : 

* 牛肉(シチュー用で良い):適量(お好きなだけどうぞ)
* にんにく:お好みで1/2個
* 馬鈴薯:2個
* 玉葱:1個
* 人参:1本
* セロリ:2本
* 固形コンソメの素:1個
* デミグラスソース缶:2缶
* ローリエ:2本
* トマトジュース:2本
* トマトケチャップ:大さじ3
* 水:1000cc
* 塩コショウ:適量
* 生クリーム:適量
* パセリ、セージ、ローズマリー、タイム:お好みで適量
* グリーンピース:お好みで1缶

作り方 : 

1. 肉を赤ワインに1時間程漬けておきます。
2. 漬けておいた肉だけを取り出し、焼き色がつくまで炒めましょう。(お好みですが、にんにくがあれば一緒に炒めても良いかもしれません。)
3. 次に別途フライパンでスライスしたセロリと玉葱を炒めます。
4. 2と3を一緒にしてローリエを入れた状態で、あくを取り除きながら弱火で1時間煮込みます。
5. 鍋にコンソメを加え、水が足りなければ付け足しながら肉が柔らかくなるまで煮込みます。
6. 肉が少し柔らかくなってきたところで人参、馬鈴薯を入れて煮込みます。

7. トマトジュース・デミグラスソース・ケチャップを加え、更に焦がさない様にかき混ぜながら中火で煮込みます。(隠し味で醤油などを少々加えても良いでしょう。)
8. お好みで、シーズニング(セージ、ローズマリー、タイム)を加えても良いでしょう。
9. 塩コショウで味を整え、器に盛ったら生クリームとパセリ(グリーンピースでも可)をかけて完成です。

次に、このファイルの内容を簡易に表示するプログラムを書きます。

ファイル名は、"cat.rb" などとして下さい。

# 『ルビー猫 第壱版』 Ruby CAT version 1.
# UNIX コマンドの cat を模倣してみます。

# ビーフシチューのレシピ
recipe = "beefstew_recipe.txt"

# レシピを開いて読みます。
open(recipe, "r"){ |io|
    while line = io.gets
        puts line
    end
}

実行時、コンソール画面。

C:\rubycode\3minutes2cooking>ruby cat.rb

『ビーフシチューのレシピ』

材料 :

* 牛肉(シチュー用で良い):適量(お好きなだけどうぞ)
     :
   (中略)
     :
9. 塩コショウで味を整え、器に盛ったら生クリームとパセリ(グリーンピースでも可)
をかけて完成です。

C:\rubycode\3minutes2cooking>

ちゃんと表示できましたね。

実行した流れは、まず組み込み関数である "open" でファイルを開きます。
その "open"にブロックを用意して、ブロック内で一行ずつ読み込んでは表示することを繰り返します。ファイルの終わりまで来たらループが終了してブロックの終わりに行きます。ブロックの終わりではちゃんとファイルを閉じてくれるのです。

これが一番シンプルに実装できたような気がしますが、前回ご紹介しました例外処理を行っていません。

これをちょっと変更して例外処理を組み込んでみましょう。

まず、例外処理を書けるように先ほどのコードを少しばらしてみましょう。

先ほどのソースコードを変更します。

# 『ルビー猫 第壱版』 Ruby CAT version 1.
# UNIX コマンドの cat を模倣してみます。

# ビーフシチューのレシピ
recipe = "beefstew_recipe.txt"

# レシピを開きます。
file = open(recipe, "r")

# レシピを読みます。
while line = file.gets
    puts line
end

# レシピを閉じます。
file.close

実行時、コンソール画面。

C:\rubycode\3minutes2cooking>ruby cat.rb

『ビーフシチューのレシピ』

材料 :

* 牛肉(シチュー用で良い):適量(お好きなだけどうぞ)
     :
   (中略)
     :
9. 塩コショウで味を整え、器に盛ったら生クリームとパセリ(グリーンピースでも可)
をかけて完成です。

C:\rubycode\3minutes2cooking>

先ほどと全く同じことが出来ることを確認しました。
ブロックで標準出力に印字していた処理をブロックの外に取り出しただけです。
そして、明示的にファイルを閉じる操作を行っています。

さあ準備が出来ましたので例外処理を加えてみましょう。

例外処理を埋め込みます。

先ほどのソースコードを変更します。

# 『ルビー猫 第壱版』 Ruby CAT version 1.
# UNIX コマンドの cat を模倣してみます。

# ビーフシチューのレシピ
recipe = "beefstew_recipe.txt"

# レシピを開きます。
file = open(recipe, "r")

begin
    # レシピを読みます。
    while line = file.gets
        puts line
    end

# システム例外が起こった時
rescue SystemCallError => sce
    puts sce.message

# その他の例外が起こった時
rescue => ex
    puts ex.message

ensure 
    # レシピを閉じます。
    file.close
end

実行時、コンソール画面。

C:\rubycode\3minutes2cooking>ruby cat.rb

『ビーフシチューのレシピ』

材料 :

* 牛肉(シチュー用で良い):適量(お好きなだけどうぞ)
     :
   (中略)
     :
9. 塩コショウで味を整え、器に盛ったら生クリームとパセリ(グリーンピースでも可)
をかけて完成です。

C:\rubycode\3minutes2cooking>

前回ご紹介した例外処理をレシピを読むプログラムに組み込むことが出来ました。。
これでレシピを読んでいる途中で何か問題が起きたら例外処理を指定することがプログラム中で可能になりますね。

"rescue" で例外を指定することで特定の例外だけ補足することが出来ます。場合に応じて判定を分けることによって異なるを処理を使い分けできますね。

一番重要な部分は "ensure"で「ファイルを閉じる」動作を確実にやってくれる筈ですので、これで安心です。

皆さんも必要に応じて例外処理を組み込んで下さい。きっと有用に機能することでしょう。

先ほどまでの例外処理で充分なのですが、もう少し踏み込んで「レシピが無かった時(ファイルが無かった時)」も処理出来るようにしてみましょう。

先ほどのソースコードを変更します。

# 『ルビー猫 第壱版』 Ruby CAT version 1.
# UNIX コマンドの cat を模倣してみます。

# クリームシチューのレシピ
recipe = "creamstew_recipe.txt"

begin
    # レシピを開きます。
    file = open(recipe, "r")

# 例外が起こった時
rescue Errno::ENOENT => ex
    puts "お探しのレシピがありません。"
    puts "他のレシピをご覧下さいませ。"
    # puts ex.message
    
    # プログラムを中断します。
    exit 1
end

begin
    # レシピを読みます。
    while line = file.gets
        puts line
    end

# システム例外が起こった時
rescue SystemCallError => sce
    puts sce.message

# その他の例外が起こった時
rescue => ex
    puts ex.message

ensure 
    # レシピを閉じます。
    file.close
end

実行時、コンソール画面。

C:\rubycode\3minutes2cooking>ruby cat.rb
お探しのレシピがありません。
他のレシピをご覧下さいませ。

C:\rubycode\3minutes2cooking>

今度は「クリームシチューのレシピ」を読んでみようと想いますが、レシピをファイルとして用意しておりませんので、例外処理にてその旨を表示してみました。

例外処理の判読する範囲を二箇所に別けてありますので、ちょっとくどいコードになってしまいましたね。

このコードも頑張ればもうちょっと少しスマートに書ける筈です。皆さんはもっとスマートに書けるように試して頂ければと想います。(解答例はいつかご紹介しますね。)

今回はファイル操作の最初である「ファイルをひらく」ことと、前回のおさらいで「例外処理」についてもお話しました。これで例外処理がどのように使うことが出来るのか?を実感して頂けるのかと期待しています。

次回あたりにはファイルの操作だけに注力してお話できるかと想います。お楽しみに。*1





「おなかが鳴ると♪やってくる♪なかまを連れて♪やってくる♪」

今日はここまで。次回をお楽しみに。

*1:-実はこれが発端となり次回以降ちょっとの間「ルビー猫」シリーズとなってしまいました。その顛末は次回以降見ていただくとお分かりになります。宜しければ暫しお付き合いの程をお願い致します。-