Feature #4592

Tempfileを直接保存したい

Added by xibbar (Takeyuki Fujioka) about 1 year ago. Updated about 1 month ago.

[ruby-dev:43412]
Status:Assigned Start date:04/21/2011
Priority:Normal Due date:
Assignee:matz (Yukihiro Matsumoto) % Done:

0%

Category:lib
Target version:-

Description

Tempfileは一時ファイルなので、プロセスが消えたり、#closeすると、 ファイルが消えてしまいます。 Tempfileのデータを保存するために 一旦読みだして、書き込み用に別ファイルを開いて、 そこに書きこまなければいけません。 これが小さいファイルだったらいいのですが、 大きいファイルになると、 Tempfile#save みたいなメソッドを用意して、 closeと同時に保存ができると、 読みだして書きこむという無駄をなくすことができます。 10MB程度だったらいいのですが、500MとかのTempfileだと かなり有効なメソッドだと思います。

History

Updated by sakuro (Sakuro OZAWA) about 1 year ago

#close(real=false)したあと、#path を使って、保存したいところに File#rename とか、File#link を使うとよいと思います。

Updated by sakuro (Sakuro OZAWA) about 1 year ago

先頭が # だと丸ごと見えなくなるのか…

#close(real=false)したあと、#path を使って、保存したいところに File#rename とか、File#link を使うとよいと思います。

Updated by mrkn (Kenta Murata) about 1 year ago

Tempfile#mv(path) というメソッドを追加するパッチを書いてみました。 https://gist.github.com/933915

File.rename してるので、元のファイルが無くなっちゃいますし、 元のファイルと同じファイル名のまま維持したい場合は使えなかったりします。

Updated by sakuro (Sakuro OZAWA) about 1 year ago

FileUtilsと間違えた。renameやlinkはFileのクラスメソッドでした。

Updated by shyouhei (Shyouhei Urabe) about 1 year ago

  • closeと同時というのを諦め、closeのちょっと後でよければ、普通にmvできるのではないでしょうか。

    irb(main):001:0> f = Tempfile.new('')
    => #<File:/tmp/20110421-7098-1bvjwc0>
    irb(main):002:0> f.puts("foobar")
    => nil
    irb(main):003:0> f.close; File.rename(f, "tmp.txt")
    => 0
    irb(main):008:0> File.read("tmp.txt")
    => "foobar\n"
  • /tmpとRubyのカレントディレクトリが別パーティションだったら、どのみちコピーは発生するのではないでしょうか。
  • Tempfileを保存したいというのはTempfileの意味からして本末転倒なのではないでしょうか。

といった感想を抱きました。

Updated by xibbar (Takeyuki Fujioka) about 1 year ago

卜部さんの言うとおりなのですが、ユースケースを書きますと、 Railsもcgi.rbも巨大なファイルをアップロードしたときは tempfileにファイルを保存します。 これを保存したいとなったときに、 tempfileから読みだして、別ファイルをオープンして 書きこむという手間とメモリが必要なので、 tempfileに入っているんだから、そのままリネームでもして 保存出来ればいいのになと思ったのでした。

ちなみに卜部さんのやり方ももちろんOKですが、 私的にはHTTP Requestをまたいで使いたいので、 tempfileを消えないようにだけするという対応でも OKなのでした。tempfile名をセッションにでも入れて、 次のリクエストでまた開くということをやりたかったです。

Updated by mame (Yusuke Endoh) about 1 month ago

  • Description updated (diff)
  • Status changed from Open to Assigned
  • Assignee set to mame (Yusuke Endoh)

Updated by akr (Akira Tanaka) about 1 month ago

remove_finalizer とか、save とかよりももうちょっと長い名前がいいんじゃないかなぁ、と思います。

Updated by ko1 (Koichi Sasada) about 1 month ago

(2012/03/25 15:33), akr (Akira Tanaka) wrote: > remove_finalizer とか、save とかよりももうちょっと長い名前がいいんじゃないかなぁ、と思います。  mv なり hardlink などして,File を返すインターフェースとかだと良かった りしないでしょかね.「消されない」Tempfile ってのに違和感がありまして.  Tempfile#mv(filepath) #=> File とか,cp でもいいか. -- // SASADA Koichi at atdot dot net

Updated by mame (Yusuke Endoh) about 1 month ago

どういう意味でこのチケットを自分にアサインしたか忘れてしまったのですが。 shyouhei (Shyouhei Urabe) wrote: > * closeと同時というのを諦め、closeのちょっと後でよければ、普通にmvできるのではないでしょうか。 > irb(main):001:0> f = Tempfile.new('') > => #<File:/tmp/20110421-7098-1bvjwc0> > irb(main):002:0> f.puts("foobar") > => nil > irb(main):003:0> f.close; File.rename(f, "tmp.txt") > => 0 > irb(main):008:0> File.read("tmp.txt") > => "foobar\n" これは、GC タイミングによっては失敗しますよね。(f.close の直後で GC) また、rename 後に元のファイル名と同じファイルを作ったら、この tempfile が GC される際に消されてしまう危険があると思います。 よって、workaround としては推奨しかねるものだと思います。 > * /tmpとRubyのカレントディレクトリが別パーティションだったら、どのみちコピーは発生するのではないでしょうか。 気にするなら、Tempfile 生成ディレクトリを自分で指定すればいいと思います。 > * Tempfileを保存したいというのはTempfileの意味からして本末転倒なのではないでしょうか。 これは個人の感覚の問題だと思いますが、「temporary だけど、うまく行けば 永続化するつもり」というのは私はいいかなあと思いました。 akr (Akira Tanaka) wrote: > remove_finalizer とか、save とかよりももうちょっと長い名前がいいんじゃないかなぁ、と思います。 Tempfile#persist とか、秋葉原の開発者会議で出た案でしたっけ。 -- Yusuke Endoh <mame@tsg.ne.jp>

Updated by mame (Yusuke Endoh) about 1 month ago

  • Assignee changed from mame (Yusuke Endoh) to matz (Yukihiro Matsumoto)
mame (Yusuke Endoh) wrote: > どういう意味でこのチケットを自分にアサインしたか忘れてしまったのですが。 思い出しました。開発者会議で出た内容をまとめて matz に振るのでした。 しかし開発者会議で出た内容を正確に覚えてないんですが、 - ユースケースは理解できる - 卜部さんの workaround は推奨されない - 良い API・名前はなんだろう くらいだったと思います。間違ってたら正してください > 参加者 matz が直接判断しなくても、tempfile.rb のメンテナになってくれる人が いれば判断できると思います。 まあメンテナになるのに matz の承認が必要ですが。 あと訂正。 > これは、GC タイミングによっては失敗しますよね。(f.close の直後で GC) これは間違いでした。f の参照が残っているので GC されることはありません。 でも race condition の問題はあるので、やはり推奨はされない、という話 だったと思います。 -- Yusuke Endoh <mame@tsg.ne.jp>

Updated by ko1 (Koichi Sasada) about 1 month ago

(2012/04/02 21:50), mame (Yusuke Endoh) wrote: > くらいだったと思います。間違ってたら正してください > 参加者  間違ってないですが,個人的には Tempfile インスタンスのまま消えないのは 不思議なので,Tempfile#xxx #=> File みたいなメソッド xxx があるといいん じゃないかなぁ,と.って,[ruby-dev:45436] に書いてるじゃん. -- // SASADA Koichi at atdot dot net

Also available in: Atom PDF