R6RSの範囲でファイルの末尾位置を取得する方法な無い(はずな)ので、outputポートのみを使うという方法は不可能である。となれば、input/outputポートを使用して、ポートを開いた直後に全部読み取ればポートの位置が末尾になるはず。ということで、こんなスクリプトで実験。
(import (rnrs)) (define out-file "out.txt") (unless (file-exists? out-file) (call-with-output-file out-file (lambda (p) (put-string p "hello\n")))) (let ((in/out (open-file-input/output-port out-file (file-options no-fail no-truncate)))) (display (utf8->string (get-bytevector-all in/out))) (put-bytevector in/out (string->utf8 "hello\n")) (close-port in/out)) ;; これを忘れていた #| 期待される出力結果。 1. hello 2. hello hello so on |#予定通りなら、期待される出力結果になって、末尾に追加されていることになる。とりあえず、Ypsilon、Mosh、Sagittarius、Chez、LarcenyとRacketで試してみた。
Attempts to read all bytes until the next end of file, blocking as necessary. If one or more bytes are read, get-bytevector-all returns a bytevector containing all bytes up to the next end of file. Otherwise, get-bytevector-all returns the end-of-file object. The operation may block indefinitely waiting to see if more bytes will become available, even if some bytes are already available.
上記の検証は嘘であることが発覚した。単にポートの閉じ忘れで、ポートを閉じないと、Ypsilon、MoshとLarcenyでは溜め込んだバッファをflushしないだけだった。逆にいうと、Chez、RacketとSagittariusではその辺に寛容でプログラム終了時(だと思う、SagittariusではGC時)にポートのflushを行っているというだけだろう。
恥ずかしい検証をしたけど、自分への戒めとして残しておくことにしよう・・・
No comments:
Post a Comment