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