お題
Math::PI の値をファイル pi.txt に書き出してください。
コード
File.open("pi.txt", "w") do |f|
f.print Math::PI
end
改善
ファイルに書き出す専用のメソッド IO.write があります。
これを用いると
IO.write("pi.txt", Math::PI)
と簡素化できます。
IO.write は File.write とも書けます。これについては次節で述べます。
ファイル読み込みのほうも同様で,
text = nil
File.open("text.txt") do |f|
text = f.read
end
とか1
text = File.open("text.txt"){ |f| f.read }
などとしなくても,IO.read を使って
text = IO.read("text.txt")
と書けます。
IO.read は File.read とも書けます(次節参照)。
IO.write/IO.read か File.write/File.read か
IO.read や IO.write を使ったコードを RuboCop で検査すると,セキュリティーの観点から「IO.write でなく File.write を使う」ように言われます2。
というのは,File.read や File.write はファイルの読み書きしかできませんが,IO.read や IO.write はファイル以外のさまざまなものに対しても読み書きでき,第一引数に与えるものによってはコマンドの実行すらできてしまうからです。
例えば,
IO.read("| mkdir hoge")
とやると,ディレクトリーが作れてしまいます!3
よって,たとえばウェブアプリでユーザー入力に基づく値を第一引数に与えることはコマンドインジェクション攻撃に繋がり得ます。
そういう観点からすると,この記事の対象読者(初心者を想定)に IO.write や IO.read を勧めるのは良くない気もしますね。
File.write や File.read を使う,と覚えておいたほうがよいかもしれません。