From: Yukihiro Matsumoto Date: 2008-03-03T16:29:49+09:00 Subject: [ruby-list:44719] Re: パイプ経由コマンド実行? まつもと ゆきひろです In message "Re: [ruby-list:44718] Re: パイプ経由コマンド実行?" on Mon, 3 Mar 2008 15:52:34 +0900, "M. Morita" writes: |I/O の open(fnm,"w").write は完結した処理だと思っていたのですが、 |実装は違っているようですね。 | | % ruby | open("foo","w").write("a\n") | open("foo","w").write("b\n") まず、openによって作られたファイルへの書き込みは内部のバッファ に格納されます。それが実際に書き込まれるのは * 改行があった * バッファがいっぱいになった * 明示的にflushした * closeした ときです。バッファリングするのは性能上の理由です。毎回書き込 みをするとプログラムのIO性能が低下するからです。 上のプログラムでは最初の行でopenしていますが、一度writeしたあ と放置されていますので、IOオブジェクトは今後書き込みがあるか もしれないので、バッファをflushしません。openの戻り値を他で参 照していないので、人間は「もう終わった」と思うかもしれません が、それはRubyの関知するところではないからです。 そのまま2行目で同じファイルをopenしています。これも同様に writeされた結果はバッファに格納されたままです。 で、このプログラムは実際にはcloseを行うことなくこのまま終了し てしまうのですが、さすがに書き込んだはずのデータがflushも closeもされていないという理由でプログラム終了と共にバッファご と消滅してはまずいので、プログラム終了時にバッファの内容を書 き込みます。その順番は不定です。 この場合、同じファイルに対してふたつIOをopenしていますので、 お手元ではたまたま最初にopenしたIOが 後に flushしたので二番 目の書き込みが生き残った形になります。 |で結果は foo は "b" が書き込まれると持っていたのですが | | % cat foo | a | |なのですね。最初の I/O をひきずってしまうのですね。 |思っていた程、単純でないようです。 どのように思っていらっしゃったかは知る由もないのですが、はっ きり言えることは「なんらかの方法でちゃんとcloseしてください」 です。 まつもと ゆきひろ /:|)