The basics of file i/o with XLISP:
To open a file for input, use the open function with the keyword argument :direction set to :input.
To open a file for output, use the open function with the keyword argument :direction set to :output.
To close a file, use the close function.
The open function takes a single
required argument which is the name of the file to be opened. This name can
be in the form of a string or a symbol.
In order to manipulate the file, it is necessary to save the value returned by the open function. This is usually done by assigning it to a variable with the setq special form or by binding it using let or let*. Here is an example:
(setq file-stream (open "init.lsp" :direction :input))
Evaluating this expression will result in the file 'init.lsp' being
opened. The file object that will be returned by the
open function will be
assigned to the variable '
It is now possible to use the file for input.
(read file-stream)
Evaluating this expression will result in reading the first expression from the file 'init.lsp'. The expression will be returned as the result of the read function. More expressions can be read from the file using further calls to the read function. When there are no more expressions to read, the read function will return NIL [or whatever value was supplied as the second argument to read].
Once you are done reading from the file, you should close it. To close the file, use the close function:
(close file-stream)
Evaluating this expression will cause the file to be closed.
Writing to a file is pretty much the same as reading from one. You need to open the file first. This time you should use the open function to indicate that you will do output to the file:
(setq file-stream (open "test.dat" :direction :output))
Evaluating this expression will open the file 'test.dat' for output.
It is now possible to write to this file by supplying the value of the
'
(print "Hello there" file-stream)
Evaluating this expression will result in the string
Once you are done writing to the file, you should
(close file-stream)
Evaluating this expression will close the output file and make it permanent.
This example shows how to open a file, read each Lisp expression from the file and print it. It demonstrates the use of files and the use of the optional 'stream' argument to the read function.
(do* ((file-stream (open "test.dat" :direction :input)) (expression (read file-stream) (read file-stream))) ((null expression) nil) (print expression))
To make sure that the file gets closed in the end, the
(let ((file-stream (open "test.dat" :direction :input))) (unwind-protect ;; protect-form (do ((expression (read file-stream) (read file-stream))) ((null expression) nil) (print expression)) ;; clean-up form (when file-stream (close file-stream))))
This pattern can be found in many
(let ((file-stream (open filename :direction direction))) (unwind-protect (progn ;; do something with the file-stream ) (when file-stream (close file-stream))))
Note that these function are meant to prevent accidents during basic
The Nyquist listdir function can be used to test if a directory exists:
(defun directory-exists-p (string) (and (listdir string) t))
Testing if a file exists is a bit more tricky because on Unix [including
Linux and
(defun file-exists-p (string) (or (stringp string) (error "not a string" string)) (unless (listdir string) (let ((file-stream (open string))) (when file-stream (close file-stream) string))))
Before creating a new file it's always a good idea to check if a file or directory with the same name already exists:
(defun file-or-directory-exists-p (string) (or (stringp string) (error "not a string" string)) (when (or (listdir string) (let ((file-stream (open string))) (when file-stream (close file-stream) t))) string))