File Reading in Lisp
Some Template Examples
These data files are used in the following four examples:
testfile1.txt:
100 212
4
4 1 124 421
124 124 142
2434
testfile2.txt:
Hello this
is a test
file.
1. Example 1, readfile1.lsp, reading numbers from a file until EOF.
The third argument to "read" specifies a symbol to be returned when
the end-of-file is reached. In the stop test for the do loop, this
return symbol tells the loop when to halt.
The general form is: (read infile nil 'return-symbol)
And for the stop test: ((eql value 'return-symbol) 'return-value)
Note that this is necessary for clisp. With another lisp product,
the following could work:
(read infile nil) and stop condition: ((not value))
(defun readfile ()
(with-open-file (infile "testfile1.txt"
:direction :input)
(do ((num (read infile nil 'eof) (read infile nil 'eof)))
((eql num 'eof) 'done) ;; End of loop test
(format t "~a~%" num)
)
)
)
Output:
> (readfile)
100
212
4
4
1
124
421
124
124
142
2434
DONE
Analysis:
The do loop has the form:
(do ((var1 init-form update-form))
(test-for-end value-to-return-at-end)
(body of loop)
)
The read function call: (read infile nil 'eof)
means:
1. "infile": read a Lisp symbol from infile
2. "nil": do not return an error upon eof
3. "'eof": return the symbol 'eof when the end of file is reached
The stop condition for the loop: ((eql num 'eof) 'done)
means that when "num" equals the symbol 'eof, returned from the read,
end the loop.
2. Example 2, readfile2.lsp, reading characters from a file and
echo printing each character.
NOTE: For those who want to know, to represent a character in Lisp,
use #\ For example (char "hello" 1) returns #\e
(defun readfile ()
(with-open-file (infile "testfile2.txt"
:direction :input)
(do ((ch (read-char infile nil 'eof) (read-char infile nil 'eof)))
((eql ch 'eof) 'done)
(format t "~a" ch)
)
)
)
Output:
> (readfile)
Hello this
is a test
file.
DONE
3. Example 3, readfile3.lsp, reading Lisp symbols from a file.
(defun readfile ()
(with-open-file (infile "testfile2.txt"
:direction :input)
(do ((sym (read infile nil 'eof) (read infile nil 'eof)))
((eql sym 'eof) 'done)
(format t "~a~%" sym)
)
)
)
Output:
> (readfile)
HELLO
THIS
IS
A
TEST
FILE.
DONE
In the example above, each symbol is printed on a separate line.
These are NOT strings, they are Lisp atoms.
4. Example 4, readfile4.lsp, reading lines from a file.
NOTE: these are STRINGS.
(defun readfile ()
(with-open-file (infile "testfile2.txt"
:direction :input)
(do ((line (read-line infile nil 'eof) (read-line infile nil 'eof)))
((eql line 'eof) 'done)
(format t "~a~%" line)
)
)
)
Output:
> (readfile)
Hello this
is a test
file.
DONE