Lisp - Reading Data From Streams
Understanding how to reading data from streams is very important in order to work with I/O in LISP. In this chapter, we'll explore various methods to read data from streams in various ways.
Core Input Functions
read() function
read() is a primary function to read data or LISP objects from streams.
read() function parses the input stream, interprets the characters read as LISP form and returns the corresponding LISP object.
This function can handle multiple type of data as inputs like symbols, numbers, lists and strings.
By default, read() method reads from *standard-input*. We can specify other streams as well using optional stream parameter.
read-char() function
read-char() is a specialized function to read a single character from an input stream.
This function is useful in performing char-by-char processing.
read-line() function
read-char() is a specialized function to read a line of text from an input stream upto new line character. New line character is included in the returned string.
This function returns the new line as a string.
read-byte() function
read-byte() is a specialized function to read binary data from a stream.
This function reads a single byte from a stream and returns an integer.
peek-char() function
peek-char() functions allows us to inspect next available character in the stream without actually consuming it.
This function is useful when we need to check what is coming as next in the stream.
Key Considerations
Standard Input
A special variable *standard-input* represents the default input stream, generally connected to the keyboard. read functions use *standard-input* by default but we can provide other stream as input as well.
EOF (End of File) handling
While reading a stream, we should handle EOF to mark end of stream. Most of the input functions accepts optional parameters as eof-error-p and eof-value in order to control how to handle EOF is handled.
eof-error-p − returns true if error occured when EOF is encountered.
eof-value − allows to return a value instead of error when EOF is encountered.
Error Handling
During I/O operations, error can popup in any form like invalid syntax, or error during I/O etc. Error should be handled properly in streams operation.
Example - Reading a File
In following example, we're reading a file test.txt lying in current folder with following content.
Welcome to LISP It is an easy to learn language.
main.lisp
; open test.txt in read mode
(let ((input-stream (open "test.txt" :direction :input)))
(when input-stream ; if file is readable
(loop for line = (read-line input-stream nil) ; read each line using read-line function
while line ; if line is present
do (format t "Read line: ~a~%" line)) ; print the line
(close input-stream))) ; close the stream
Output
When you execute the code, it returns the following result −
Read line: Welcome to LISP Read line: It is an easy to learn language.
Explanation
open function is used to open test.txt in read mode.
read-line function is used to read file line by line until nil is returned.
close function is used to close the file after reading it completely.