FunctionPackage: exclToCDocOverviewCGDocRelNotesFAQIndexPermutedIndex
Allegro CL version 10.1
Unrevised from 10.0 to 10.1.
10.0 version


Arguments: string &optional stream (eof-error-p t)eof-value &key (start 0) end

This function is a faster variant of read-line designed to place characters, read from a stream, into an existing string. It differs from read-line in (1) using an existing string rather than creating a new one, (2) reading only as many characters from a line as are needed, rather than reading a whole line, and (3) not returning the string where the characters are placed. Instead, filling the string is a side effect and two information values are returned:

  1. The number of characters read and stored, (not including a newline if read). If an eof is encountered without reading any characters and eof-error-p was nil, then eof-value is returned instead. An error is signaled if an eof is encountered immediately and eof-error-p is non-nil (its default is t). If any characters are read (including a newline character), no error will be signaled and this first returned value will be an integer.
  2. A flag indication the reason reading was stopped. The value nil indicates a newline was encountered (as with read-line, reading will not continue after a newline and the newline character will not be added to string). The value :eof means an end of file was encountered. The value :short means that character reading was stopped because the end of the string (the actual end or the end specified by the end keyword argument) was reached.

    Unexpected :short instead of nil. When the number of characters in a line is exactly the numbers of characters specified by start and end, this second return value will be :short instead of nil. Characters are read until the portion of the string specified by start and end is filled. The character after the one read which fills the substring is not read. If it is a newline, then in fact the whole line will be copied into string (just as if end was unspecified and the string was larger) but the system will not know that to be the case. If further reading is done when the next unread character is a newline, no characters will be read and 0 and nil will be the return values.

A traditional way to fill a string with characters from a file is to read a line from the file with read-line and copy characters from the string read into the target string. But that process is costly in time and space, as new strings must be allocated by read-line, and characters are copied twice (from the stream to the new string and from the new string to the target string). This function is optimized for the specific purpose of copying characters from a stream into an existing string.

The characters are read from stream and placed into string, beginning at the position specified by start. Characters are continually read until

  1. The end argument is satisfied (the value nil for end is the same as specifying (length string)).
  2. A newline is encountered (as with cl:read-line, it is not added to the string).
  3. An eof is encountered.

If the :short situation occurs (i.e. the end argument is satisfied without having encountered a newline) then further processing can be done in subsequent calls without loss of data. It should therefore be possible if desired to implement cl:read-line using excl:read-line-into.


The motivation for this function is to provide read-line functionality without an open-ended consing of result strings, and to allow for more control over line-oriented input.


Assume file is a stream open to a file with contents shown (there are no space characters, the blank line has just a newline character, and the last line ends with an eof, not a newline):

first line
second line

fourth line
last line

Calls to excl:read-line-into have the following results:

;;  Edit to have FILE be a stream open to the file specified above:
;;  (setq file (open "" :direction :input)

(setq string1 "0123456789" string2 "0123456789012345" 
      string3 "012345678901234567890")
(read-line-into string1 file) -> 10 :short
string1 -> "first line"
(read-line-into string2 file) -> 0 nil
string2 -> "0123456789"   ;; no characters read beause 
                          ;; a newline was encountered at once
(read-line-into string2 file nil :eof-at-once :start 0 :end 5) 
   -> 5 :short
string2 -> "secon56789012345"
(read-line-into string2 file nil :eof-at-once :start 5) -> 6 nil
string2 -> "second line12345"
(read-line-into string2 file nil :eof-at-once :start 10) -> 0 nil
string2 -> "second line12345"  ;; read blank line, no characters added
(read-line-into string3 file nil :eof-at-once :start 3) -> 11 nil
string3 -> "012fourth line4567890"
(read-line-into string3 file) -> 9 :eof
   ;;  If there is a newline at the end of the last line
   ;;  (sometimes editors insert them without being asked to)
   ;;  then this will return '9 nil' instead of '9 :eof'
string3 -> "last line line4567890"
(read-line-into string3 file nil :eof-at-once) -> :eof-at-once :eof
string3 -> "last line line4567890"
(read-line-into string3 file) -> ERROR ;; eof-error-p is T

See also simple-stream-read-line. That function is less space efficient than this one, but has a simpler interface.

Copyright (c) 1998-2022, Franz Inc. Lafayette, CA., USA. All rights reserved.
This page was not revised from the 10.0 page.
Created 2019.8.20.

Allegro CL version 10.1
Unrevised from 10.0 to 10.1.
10.0 version