(rontolisp) docs
← Macros

with-open-file

(with-open-file (stream filename options...) body...)

Opens the file named by filename, binds the open stream to stream, evaluates the body forms with that binding, and closes the file afterwards, returning the value of the last body form. On the interpreter and the JVM the expansion wraps the body in unwind-protect, so the file is closed on every exit (normal return, an error signaled in the body, or a return/return-from); this holds on every backend, including wasm-GC since the exception-handling support landed (a with-open-file program compiles in EH mode there). The supported options are :direction -- :input (the default), :output or :io -- :element-type -- 'character (the default, a text stream) or an integer type (a binary stream for read-byte/write-byte; '(unsigned-byte 8) is one octet per element, and a wider or signed type the element open describes, which on the compiled backends must be written literally) -- and the :if-exists / :if-does-not-exist / :external-format table open documents, :if-exists :append and :overwrite included. An option value may be COMPUTED: a function taking the options as arguments and passing them down is how a portable file wrapper opens a file, and such a value is read when the form runs and dispatched onto the matching literal shape. A literal value is still resolved at compile time, so the usual spelling compiles exactly as before. A value outside the supported set signals an error when the form runs. It expands into a plain open/close pair, so no special stream type is involved.

Because it touches the filesystem, with-open-file is shown here statically rather than as a runnable example:

(with-open-file (s "out.txt" :direction :output)
  (write-line "hello" s))
(with-open-file (s "out.txt" :direction :input)
  (read-line s)) ; => "hello"
(with-open-file (s "out.bin" :direction :output :element-type '(unsigned-byte 8))
  (write-byte 255 s)) ; => 255
(with-open-file (s "out.txt" :direction :output :if-exists :append)
  (write-line "again" s))
(defun read-first-line (path element-type)
  (with-open-file (s path :direction :input :element-type element-type)
    (read-line s)))