Ports, Files and I/O

36.1 Console I/O

(import (scheme base) (scheme write) (scheme read))
(display "text")              ; human-readable
(write "text")                ; machine-readable: "text" with quotes
(write-shared x) (write-simple x)   ; with/without shared-structure labels
(newline)
(write-char #\a) (write-string "abc") (write-u8 65 binary-port)
(flush-output-port)
(define line (read-line))     ; from (current-input-port); returns an eof object at EOF
(define datum (read))         ; read an s-expression
(read-char) (peek-char) (read-string 5) (char-ready?)
(eof-object? (read-char (open-input-string "")))   ; #t
(eof-object)                  ; the eof object itself

36.2 Files

(import (scheme file))

;; Write
(call-with-output-file "notes.txt"
  (lambda (port)
    (write-string "Line 1\n" port)
    (display "Line 2" port)
    (newline port)))

;; Read line by line
(define (read-lines filename)
  (call-with-input-file filename
    (lambda (port)
      (let loop ((line (read-line port)) (acc '()))
        (if (eof-object? line)
            (reverse acc)
            (loop (read-line port) (cons line acc)))))))
(read-lines "notes.txt")      ; ("Line 1" "Line 2")

;; Redirect the current ports
(with-output-to-file "out.txt" (lambda () (display "redirected")))
(with-input-from-file "out.txt" read-line)   ; "redirected"

;; Explicit ports
(define out (open-output-file "log.txt"))
(display "entry" out)
(close-port out)
(file-exists? "log.txt")      ; #t
(delete-file "log.txt")

;; Binary files
(define bin (open-binary-input-file "image.png"))
(read-bytevector 8 bin)       ; the first 8 bytes
(close-port bin)

;; Reading and writing s-expression data files (trivial in Scheme!)
(call-with-output-file "db.scm" (lambda (p) (write '((ana . 30) (bo . 25)) p)))
(call-with-input-file "db.scm" read)   ; ((ana . 30) (bo . 25))

36.3 String Ports

(define out (open-output-string))
(write 'hello out)
(display " world" out)
(get-output-string out)       ; "hello world"

(define in (open-input-string "(1 2 3) foo \"bar\""))
(read in) (read in) (read in) ; (1 2 3) foo "bar"

(define (to-string obj)
  (let ((p (open-output-string))) (write obj p) (get-output-string p)))
;; Bytevector ports: open-input-bytevector, open-output-bytevector, get-output-bytevector