Tempfileクラスを使って、一時ファイルを作成し、そやつをrenameする方法。
- きっかけ
ファイルの先頭に文字列を追加したくて、『Rubyレシピブック』をぱらぱらめくると、「#163 ファイルに1行挿入する」なんて項目を見つけたので、そのままコピペ。
要するにTempfileクラスを使って一時ファイルを作成してファイルの内容をコピー。該当行にきたら挿入したいデータを追記して、一時ファイルを作成完了。最後にrenameして終了というのがこのレシピの本質。
- 正誤表は大事
『Rubyレシピブック』に限らず、こういう本を読むときは、必ず正誤表をチェックしておこう。今回のレシピでは2件の正誤情報が報告されているので、目を通しておかないとちょっぴり痛い目にあいます。(と、あった本人が言う。)
- GCは気ままに生きる
ガーベージコレクタ(GC)って便利なものですよね。C++のmalloc - freeな関係やnew - deleteってな関係に疲れていると、「使ったらそのまんま」「後片付けはメイドさんがやってくれる」的なGCは快適そのものです。
さてさて、そろそろ本文。
Tempfileクラスを使って一時ファイルを作成した後、削除してくれるのもGCなんですが、また処理しきってないのに一時ファイルを削除しちゃうと「ファイル作っても0バイト〜」ってな状態になったりします。というわけで、GCに対して「まだこいつ生きているよ〜〜〜」って言うのが必要なんですが、どないすればええのやら・・・
でいろいろやった結果、一時ファイルに情報を書き込んだ後、一旦closeして再度openしちょります。これが有効なのかどうかは分かりませんが、これで「ファイル作っても0バイト〜」ってことはなくなりました。
- 最後はrenameのはずだった・・・
で、これで万事OK牧場!!って思って実行すると、こんなエラーが出てきました。
renametry.rb:18:in `rename': Permission denied - ./mytemp3124.0 or ddd.cpp (Errno::EACCES)
from renametry.rb:18
どうやらパーミッションがダメよんって言っている様なのですが、動かしている
のはWindows。なんでこんなもんが出てくるんでしょう。わけ分かりません。
さらに、よくよくメッセージを見ると「./mytemp3124.0かddd.cppのどっちかがへんだよ〜」って言ってんだけれども、どっちが悪いのかが分からん。解決の手がかりすらねぇよ。
こういうときは、問題の切り分けを行わなければいけない。まず、どっちが悪いかを見極めることにする。
まず、./mytemp3124.0の内容をファイルにコピーすることにする。これは、FileUtilsモジュールにあるcp関数を使ってみると見事に成功。
次にrenameの代わりにFileUtilsモジュールにあるmv関数を使ってみることにする。
すると、
C:/ruby/lib/ruby/1.8/fileutils.rb:585:in `unlink': Permission denied - ./mytemp3844.0 (Errno::EACCES)
from C:/ruby/lib/ruby/1.8/fileutils.rb:585:in `mv'
from C:/ruby/lib/ruby/1.8/fileutils.rb:572:in `fu_each_src_dest'
from C:/ruby/lib/ruby/1.8/fileutils.rb:845:in `fu_each_src_dest0'
from C:/ruby/lib/ruby/1.8/fileutils.rb:845:in `fu_each_src_dest'
from C:/ruby/lib/ruby/1.8/fileutils.rb:572:in `mv'
from renametry.rb:20
ってでたので、悪いのは一時ファイルの削除処理だろうと。というわけで、うまくいったcp関数でおしまいって感じ。
- Macでもやってみた。
MacだときっちりrenameでOK牧場。結局窓はそんな感じだ。