lispとrubyとpythonと その8 ファイルIO(common lisp)

CommonLispでのファイルIOはこんな感じ。
一般的にはwith-xxxだけど、ファイル開きっぱなしの時とかはそうできない時もある。

(require 'cl-interpol)
(cl-interpol:enable-interpol-syntax)

;;プリミティブなのはopen
;;まずはテキストファイル書き込み
;;:if-exists  :supersedeにしているから既存のファイルがあったら作り直す
;;既存のファイルに追加するなら:appendとか
;;http://www.lispworks.com/documentation/HyperSpec/Body/f_open.htm#open
(let ((ofs (open "./test.txt" :direction :output :if-exists :append :if-does-not-exist :create)))
  (unwind-protect
       (format ofs #?"hello world\n")
    (close ofs)))

;;読み込み
;;read-lineで一行読み込み
(let ((ifs (open "./test.txt" :direction :input)))
  (unwind-protect
       (do ((l (read-line ifs nil 'EOF) (read-line ifs nil 'EOF)))
    ((eql l 'EOF))
  (format t "~A~%" l))
    (close ifs)))
;;->hello world

;;バイナリファイル書き込み
(let ((ofs (open "./test.dat" :direction :output :if-exists :append :element-type 'unsigned-byte :if-does-not-exist :create)))
  (unwind-protect
       (progn 
  (write-byte 0 ofs)
  (write-byte 1 ofs)
  (write-byte 2 ofs))
    (close ofs)))

;;バイナリ読み込み
(let ((ifs (open "./test.dat" :direction :input :element-type 'unsigned-byte)))
  (unwind-protect
       (progn 
  (do ((b (read-byte ifs nil 'EOF) (read-byte ifs nil 'EOF)))
      ((eql b 'EOF))
    (format t "~A~%" b)))
    (close ifs)))
;;->0
;;  1
;;  2

;;一般的にはこっち
(with-open-file (ofs "./test2.txt" :direction :output :if-exists :append :if-does-not-exist :create)
  (format ofs #?"hello world2\n"))

(with-open-file (ifs "./test2.txt" :direction :input)
  (do ((l (read-line ifs nil 'EOF) (read-line ifs nil 'EOF)))
      ((eql l 'EOF))
    (format t "~A~%" l)))
;;->hello world2

(with-open-file (ofs "./test2.dat" :direction :output :if-exists :append :if-does-not-exist :create :element-type 'unsigned-byte)
  (write-byte 0 ofs)
  (write-byte 1 ofs)
  (write-byte 2 ofs))

(with-open-file (ifs "./test2.dat" :direction :input :element-type 'unsigned-byte)
  (do ((b (read-byte ifs nil 'EOF) (read-byte ifs nil 'EOF)))
      ((eql b 'EOF))
    (format t "~A~%" b)))
;;->0
;;  1
;;  2

;;バッファするならこんな感じ
(with-open-file (ifs "./test2.dat" :direction :input :element-type 'unsigned-byte)
  (let ((buf (make-array 16 :initial-element nil)))
    (do ((pos (read-sequence buf ifs) (read-sequence buf ifs)))
 ((= pos 0))
      (format t "~A~%" buf))))
;;->#(0 1 2 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)

;;番外編だけどseriesで読む手もある
(require 'series)
(series:iterate ((l (series:scan-file "./test2.txt" #'read-line)))
  (format t "series ~A~%" l))
;;->series hello world2