21.3. The Streams Dictionary [CLHS-21.2]

21.3.1. Function STREAM-ELEMENT-TYPE
21.3.1.1. Binary input from *STANDARD-INPUT*
21.3.2. Function EXT:MAKE-STREAM
21.3.3. Binary input, READ-BYTE, EXT:READ-INTEGER & EXT:READ-FLOAT
21.3.4. Binary output, WRITE-BYTE, EXT:WRITE-INTEGER & EXT:WRITE-FLOAT
21.3.5. Bulk Input and Output
21.3.6. Non-Blocking Input and Output
21.3.7. Function FILE-POSITION
21.3.8. Avoiding blank lines, EXT:ELASTIC-NEWLINE
21.3.9. Function OPEN
21.3.10. Function CLOSE
21.3.11. Function OPEN-STREAM-P
21.3.12. Class BROADCAST-STREAM
21.3.13. Functions EXT:MAKE-BUFFERED-INPUT-STREAM and EXT:MAKE-BUFFERED-OUTPUT-STREAM

21.3.1. Function STREAM-ELEMENT-TYPE

STREAM-ELEMENT-TYPE is SETFable. The STREAM-ELEMENT-TYPE of STREAMs created by the functions OPEN, EXT:MAKE-PIPE-INPUT-STREAM EXT:MAKE-PIPE-OUTPUT-STREAM, EXT:MAKE-PIPE-IO-STREAM, SOCKET:SOCKET-ACCEPT, SOCKET:SOCKET-CONNECT can be modified, if the old and the new STREAM-ELEMENT-TYPEs are either

Functions STREAM-ELEMENT-TYPE and (SETF STREAM-ELEMENT-TYPE) are GENERIC-FUNCTIONs, see Section 29.2, “Gray streams”.

21.3.1.1. Binary input from *STANDARD-INPUT*

Note that you cannot change STREAM-ELEMENT-TYPE for some built-in streams, such as terminal streams, which is normally the value of *TERMINAL-IO*. Since *STANDARD-INPUT* normally is a SYNONYM-STREAM pointing to *TERMINAL-IO*, you cannot use READ-BYTE in the it.

Since CGI (Common Gateway Interface) provides the form data for METHOD="POST" on the stdin, and the server will not send you an end-of-stream on the end of the data, you will need to use (EXT:GETENV "CONTENT_LENGTH") to determine how much data you should read from stdin. CLISP will detect that stdin is not a terminal and create a regular FILE-STREAM which can be passed to (SETF STREAM-ELEMENT-TYPE). To test this functionality interactively, you will need to open the standard input in the binary mode:

(let ((buf (MAKE-ARRAY (PARSE-INTEGER (EXT:GETENV "CONTENT_LENGTH"))
                       :element-type '(UNSIGNED-BYTE 8))))
  (WITH-OPEN-STREAM (in (EXT:MAKE-STREAM :INPUT :ELEMENT-TYPE '(UNSIGNED-BYTE 8)))
    (READ-SEQUENCE buf in))
  buf)

21.3.2. Function EXT:MAKE-STREAM

Function EXT:MAKE-STREAM creates a Lisp stream out of an OS file descriptor: (EXT:MAKE-STREAM object &KEY :DIRECTION :ELEMENT-TYPE :EXTERNAL-FORMAT :BUFFERED)

object designates an OS handle (a file descriptor), and should be one of the following:

number
denotes the file descriptor of this value
:INPUT
denotes CLISP process standard input
:OUTPUT
denotes CLISP process standard output
:ERROR
denotes CLISP process standard error
STREAM
denotes the handle of this stream, which should be a FILE-STREAM or a SOCKET:SOCKET-STREAM

Beware of buffering!

When there are several Lisp STREAMs backed by the same OS file descriptor, the behavior may be highly confusing when some of the Lisp streams are :BUFFERED. Use FORCE-OUTPUT for output STREAMs, and bulk input for input STREAMs.

The handle is duplicated (with dup), so it is safe to CLOSE a STREAM returned by EXT:MAKE-STREAM.

21.3.3. Binary input, READ-BYTE, EXT:READ-INTEGER & EXT:READ-FLOAT

The function (EXT:READ-INTEGER stream element-type &OPTIONAL ENDIANNESS eof-error-p eof-value) reads a multi-byte INTEGER from stream, which should be a STREAM with STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8). element-type should be type equivalent to (UNSIGNED-BYTE n), where n is a multiple of 8.

(EXT:READ-INTEGER stream element-type) is like (READ-BYTE stream) if stream's STREAM-ELEMENT-TYPE were set to element-type, except that stream's FILE-POSITION will increase by n/8 instead of 1.

Together with (SETF STREAM-ELEMENT-TYPE), this function permits mixed character/binary input from a stream.

The function (EXT:READ-FLOAT stream element-type &OPTIONAL ENDIANNESS eof-error-p eof-value) reads a floating-point number in IEEE 754 binary representation from stream, which should be a STREAM with STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8). element-type should be type equivalent to SINGLE-FLOAT or DOUBLE-FLOAT.

Endianness. ENDIANNESS can be :LITTLE or :BIG. The default is :LITTLE, which corresponds to the READ-BYTE behavior in CLISP.

21.3.4. Binary output, WRITE-BYTE, EXT:WRITE-INTEGER & EXT:WRITE-FLOAT

The function (EXT:WRITE-INTEGER integer stream element-type &OPTIONAL ENDIANNESS) writes a multi-byte INTEGER to stream, which should be a STREAM with STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8). element-type should be type equivalent to (UNSIGNED-BYTE n), where n is a multiple of 8.

(EXT:WRITE-INTEGER integer stream element-type) is like (WRITE-BYTE integer stream) if stream's STREAM-ELEMENT-TYPE were set to element-type, except that stream's FILE-POSITION will increase by n/8 instead of 1.

Together with (SETF STREAM-ELEMENT-TYPE), this function permits mixed character/binary output to a STREAM.

The function (EXT:WRITE-FLOAT float stream element-type &OPTIONAL ENDIANNESS) writes a floating-point number in IEEE 754 binary representation to stream, which should be a STREAM with STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8). element-type should be type equivalent to SINGLE-FLOAT or DOUBLE-FLOAT.

21.3.5. Bulk Input and Output

Function READ-SEQUENCEIn addition to READ-SEQUENCE, the following two functions are provided:

EXT:READ-BYTE-SEQUENCE performs multiple READ-BYTE operations:

(EXT:READ-BYTE-SEQUENCE sequence stream &KEY :START :END :NO-HANG :INTERACTIVE) fills the subsequence of sequence specified by :START and :END with INTEGERs consecutively read from stream. It returns the index of the first element of sequence that was not updated (= end or < end if the stream reached its end). When no-hang is non-NIL, it does not block: it treats input unavailability as end-of-stream. When no-hang is NIL and interactive is non-NIL, it can block for reading the first byte but does not block for any further bytes.

This function is especially efficient if sequence is a (VECTOR (UNSIGNED-BYTE 8)) and stream is a file/pipe/socket STREAM with STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8).

EXT:READ-CHAR-SEQUENCE performs multiple READ-CHAR operations:

(EXT:READ-CHAR-SEQUENCE sequence stream &KEY :START :END) fills the subsequence of sequence specified by :START and :END with characters consecutively read from stream. It returns the index of the first element of sequence that was not updated (= end or < end if the stream reached its end).

This function is especially efficient if sequence is a STRING and stream is a file/pipe/socket STREAM with STREAM-ELEMENT-TYPE CHARACTER or an input STRING-STREAM.

Function WRITE-SEQUENCEIn addition to WRITE-SEQUENCE, the following two functions are provided:

EXT:WRITE-BYTE-SEQUENCE performs multiple WRITE-BYTE operations:

(EXT:WRITE-BYTE-SEQUENCE sequence stream &KEY :START :END :NO-HANG :INTERACTIVE) outputs the INTEGERs of the subsequence of sequence specified by :START and :END to stream. When no-hang is non-NIL, does not block. When no-hang is NIL and interactive is non-NIL, it can block for writing the first byte but does not block for any further bytes. Returns two values: sequence and the index of the first byte that was not output.

This function is especially efficient if sequence is a (VECTOR (UNSIGNED-BYTE 8)) and stream is a file/pipe/socket STREAM with STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8).

EXT:WRITE-CHAR-SEQUENCE performs multiple WRITE-CHAR operations:

(EXT:WRITE-CHAR-SEQUENCE sequence stream &KEY :START :END) outputs the characters of the subsequence of sequence specified by :START and :END to stream. Returns the sequence argument.

This function is especially efficient if sequence is a STRING and stream is a file/pipe/socket STREAM with STREAM-ELEMENT-TYPE CHARACTER.

Rationale. The rationale for EXT:READ-CHAR-SEQUENCE, EXT:READ-BYTE-SEQUENCE, EXT:WRITE-CHAR-SEQUENCE and EXT:WRITE-BYTE-SEQUENCE is that some STREAMs support both character and binary i/o, and when you read into a SEQUENCE that can hold both (e.g., LIST or SIMPLE-VECTOR) you cannot determine which kind of input to use. In such situation READ-SEQUENCE and WRITE-SEQUENCE SIGNAL an ERROR, while EXT:READ-CHAR-SEQUENCE, EXT:READ-BYTE-SEQUENCE, EXT:WRITE-CHAR-SEQUENCE and EXT:WRITE-BYTE-SEQUENCE work just fine.

21.3.6. Non-Blocking Input and Output

In addition to the standard functions LISTEN and READ-CHAR-NO-HANG, CLISP provides the following functionality facilitating non-blocking input and output, both binary and character.

(EXT:READ-CHAR-WILL-HANG-P stream)

EXT:READ-CHAR-WILL-HANG-P queries the stream's input status. It returns NIL if READ-CHAR and PEEK-CHAR with a peek-type of NIL will return immediately. Otherwise it returns T. (In the latter case the standard LISTEN function would return NIL.)

Note the difference with (NOT (LISTEN stream)): When the end-of-stream is reached, LISTEN returns NIL, whereas EXT:READ-CHAR-WILL-HANG-P returns NIL.

Note also that EXT:READ-CHAR-WILL-HANG-P is not a good way to test for end-of-stream: If EXT:READ-CHAR-WILL-HANG-P returns T, this does not mean that the stream will deliver more characters. It only means that it is not known at this moment whether the stream is already at end-of-stream, or will deliver more characters.

(EXT:READ-BYTE-LOOKAHEAD stream)
To be called only if stream's STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8). Returns T if READ-BYTE would return immediately with an INTEGER result. Returns :EOF if the end-of-stream is already known to be reached. If READ-BYTE's value is not available immediately, returns NIL instead of waiting.
(EXT:READ-BYTE-WILL-HANG-P stream)
To be called only if stream's STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8). Returns NIL if READ-BYTE will return immediately. Otherwise it returns true.
(EXT:READ-BYTE-NO-HANG stream &OPTIONAL eof-error-p eof-value)
To be called only if stream's STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8). Returns an INTEGER or does end-of-stream handling, like READ-BYTE, if that would return immediately. If READ-BYTE's value is not available immediately, returns NIL instead of waiting.

21.3.7. Function FILE-POSITION

FILE-POSITION works on any :BUFFERED FILE-STREAM.

Platform Dependent: Win32 platform only.
When a #\Newline is output to (respectively input from) a file stream, its file position is increased by 2 since #\Newline is encoded as CR/LF in the file.

21.3.8. Avoiding blank lines, EXT:ELASTIC-NEWLINE

The function (EXT:ELASTIC-NEWLINE [stream]) is like FRESH-LINE but the other way around: It outputs a conditional newline on stream, which is canceled if the next output on stream happens to be a newline. More precisely, it causes a newline to be output right before the next character is written on stream, if this character is not a newline. The newline is also output if the next operation on the stream is FRESH-LINE, FINISH-OUTPUT, FORCE-OUTPUT or CLOSE.

The functionality of EXT:ELASTIC-NEWLINE is also available through the FORMAT directive ~..

A technique for avoiding unnecessary blank lines in output is to begin each chunk of output with a call to FRESH-LINE and to terminate it with a call to EXT:ELASTIC-NEWLINE.

See also doc/Newline-Convention.txt.

21.3.9. Function OPEN

OPEN accepts an additional keyword :BUFFERED.

The acceptable values for the arguments to the file/pipe/socket STREAM functions

:ELEMENT-TYPE

types equivalent to CHARACTER or (UNSIGNED-BYTE n), (SIGNED-BYTE n); if the stream is to be un:BUFFERED, n must be a multiple of 8.

If n is not a multiple of 8, CLISP will use the specified number of bits for i/o, and write the file length (as a number of n-bit bytes) in the preamble.

This is done to ensure the input/output consistency: suppose you open a file with :ELEMENT-TYPE of (UNSIGNED-BYTE 3) and write 7 bytes (i.e., 21 bit) there. The underlying OS can do input/output only in whole 8-bit bytes. Thus the OS will report the size of the file as 3 (8-bit) bytes. Without the preamble CLISP will have no way to know how many 3-bit bytes to read from this file - 6, 7 or 8.

:EXTERNAL-FORMAT
EXT:ENCODINGs, (constant) SYMBOLs in the CHARSET package, STRINGs (denoting iconv-based encodings), the symbol :DEFAULT, and the line terminator keywords :UNIX, :MAC, :DOS. The default encoding is CUSTOM:*DEFAULT-FILE-ENCODING*. This argument determines how the lisp CHARACTER data is converted to/from the 8-bit bytes that the underlying OS uses.
:BUFFERED

NIL, T, or :DEFAULT. Have CLISP manage an internal buffer for input or output (in addition to the buffering that might be used by the underlying OS). Buffering is a known general technique to significantly speed up i/o.

  • for functions that create SOCKET:SOCKET-STREAMs and pipes, :DEFAULT is equivalent to T on the input side and to NIL on the output side; it you are transmitting a lot of data then using buffering will significantly speed up your i/o;
  • for functions that open files, :DEFAULT means that buffered file streams will be returned for regular files and (on UNIX) block-devices, and unbuffered file streams for special files.

Note that some files, notably those on the /proc filesystem (on UNIX systems), are actually, despite their innocuous appearance, special files, so you might need to supply an explicit :BUFFERED NIL argument for them. Actually, CLISP detects that the file is a /proc file, so that one is covered, but there are probably more strange beasts there!

When an already opened file is opened again, a continuable ERROR is SIGNALed, unless both the existing and the new STREAMs are read-only (i.e., :DIRECTION is :INPUT or :INPUT-IMMUTABLE).

21.3.10. Function CLOSE

Function CLOSE is a GENERIC-FUNCTION, see Section 29.2, “Gray streams”.

When the :ABORT argument is non-NIL, CLOSE will not SIGNALs an ERROR even when the underlying OS call fails.

GET-OUTPUT-STREAM-STRING returns the same value after CLOSE as it would before it.

CLOSE on an already closed STREAM does nothing and returns T.

If you do not CLOSE your STREAM explicitly, it will be closed at garbage-collection time automatically. This is not recommended though because garbage-collection is not deterministic. Please use WITH-OPEN-STREAM etc.

21.3.11. Function OPEN-STREAM-P

Function OPEN-STREAM-P is a GENERIC-FUNCTION, see Section 29.2, “Gray streams”.

21.3.12. Class BROADCAST-STREAM

INPUT-STREAM-P and INTERACTIVE-STREAM-P return false for BROADCAST-STREAMs.

21.3.13. Functions EXT:MAKE-BUFFERED-INPUT-STREAM and EXT:MAKE-BUFFERED-OUTPUT-STREAM

(EXT:MAKE-BUFFERED-OUTPUT-STREAM function)Returns a buffered output STREAM. function is a FUNCTION expecting one argument, a SIMPLE-STRING. WRITE-CHAR collects the CHARACTERs in a STRING, until a newline character is written or FORCE-OUTPUT/FINISH-OUTPUT is called. Then function is called with a SIMPLE-STRING as argument, that contains the characters collected so far. CLEAR-OUTPUT discards the characters collected so far.

(EXT:MAKE-BUFFERED-INPUT-STREAM function mode)Returns a buffered input STREAM. function is a FUNCTION of 0 arguments that returns either NIL (stands for end-of-stream) or up to three values string, start, end. READ-CHAR returns the CHARACTERs of the current string one after another, as delimited by start and end, which default to 0 and NIL, respectively. When the string is consumed, function is called again. The string returned by function should not be changed by the user. function should copy the string with COPY-SEQ or SUBSEQ before returning if the original string is to be modified. mode determines the behavior of LISTEN when the current string buffer is empty:

NIL
the stream acts like a FILE-STREAM, i.e. function is called
T
the stream acts like an interactive stream without end-of-stream, i.e. one can assume that further characters will always arrive, without calling function
FUNCTION
this FUNCTION tells, upon call, if further non-empty strings are to be expected.

CLEAR-INPUT discards the rest of the current string, so function will be called upon the next READ-CHAR operation.


These notes document CLISP version 2.41Last modified: 2006-10-13