next up previous index
Next: In-memory Streams Up: Input and Output Previous: Opening New Streams   Index

Subsections

Communication with Streams

The contents of a stream may be interpreted in one of the three basic ways. The first one is to consider it as a sequence of characters, so that the basic unit to be read or written is a character. The second one interprets the stream as a sequence of tokens, thus providing an interface to the Prolog lexical analyzer and the third one is to consider a stream as a sequence of Prolog terms.

Character I/O

The get/1, 2 and put/1, 2 predicates corresponds to the first way of looking at streams. The call
get(Char)
takes the next character from the current input stream and matches it as a single character with Char. Note that a character in ECLiPSe is represented as an integer corresponding to the ASCII code of the character. If the end of file has been reached then an exception is raised. The call
put(Char)
puts the char Char on to the current output stream. The predicates
get(Stream, Char)
and
put(Stream, Char)
work similarly on the specified stream.

The input and output is normally buffered by ECLiPSe. To make I/O in raw mode, without buffering, the predicates tyi/1, 2 and tyo/1, 2 are provided.

Token I/O

The predicate
read_token(Token, Class)
represents the second way of interpreting stream contents. It reads the next token from the current input stream, unifies it with Token, and its token class is unified with Class. A token is either a sequence of characters with the same or compatible character class, e.g. ab_1A, then it is a Prolog constant or variable, or a single character, e.g. ')'. The token class represents the type of the token and its special meaning, e.g. fullstop, comma, open_par, etc.
read_token(Stream, Token, Class)
reads a token from the specified stream. A further, very flexible possibility to read a sequence of characters is provided by the built-ins
read_string(Stream, Delimiters, Length, String)
read_string(Delimiters, Length, String)
Here, the input is read up to a specified delimiter or up to a specified length, and returned as an ECLiPSe string.

Term I/O

The read/1, 2 and write/1, 2 predicates correspond to the third way of looking at streams. The goal
read(Term)
reads the next term from the current input stream and unifies it with Term. The input term must be followed by a full stop, that is, a '.' character followed by a layout character (tab, space or newline) or by the end of file. If end of file has been reached then an exception is raised, the default handler causes the atom end_of_file to be returned. A term may be read from a stream other than the current input stream by the call
read(Stream, Term)
which reads the term from the named stream. The goal
write(Term)
writes Term to the current output stream. This is done by taking the current operator declarations into account. Output produced by the write/1, 2 predicate is not (necessarily) in a form suitable for subsequent input to a Prolog program using the read/1 predicate, for this purpose writeq/1, 2 is to be used. The goal
write(Stream, Term)
writes Term to the named output stream. The predicate
display(Term)
outputs the Term on the current output stream in the functor syntax, ignoring possible operator declarations. The predicate
readvar(Stream, Term, VarList)
can be used to read a term from the specified stream and obtain the list of variable names contained in the Term. VarList is a list of pairs [VarName|Var] where VarName is the atom corresponding to the variable name and Var is the corresponding variable.

When the flag variable_names is switched off, the output predicates are not able to write free variables in their source form, i.e. with the correct variable names. Then the variables are output in the form

_aN
where a is a character which depends on the memory area where the variable is located or on its properties: l for a local variable, g for a global variable or a metaterm. N is a number.

It is possible to pass any input stream to the ECLiPSe compiler using the predicate

compile_stream(Stream)
and it is of course possible to mix the compilation with other input predicates. If, for example, the file a.pl contains the following data
p(1).
p(2).
end_of_file.
p(3).
it is possible to execute
[eclipse 1]: open('a.pl', read, a).

yes.
[eclipse 2]: read(a, X).

X = p(1)
yes.
[eclipse 3]: compile_stream(a).
a.pl    compiled 40 bytes in 0.00 seconds

yes.
[eclipse 4]: read(a, X).

X = p(3)
yes.
[eclipse 5]: p(X).

X = 2
yes.
To specify a position in the file to write to or read from, the predicate seek/2 is provided. The call
seek(Stream, Pointer)
moves the current position in the file (the 'file pointer') to the offset Pointer (a number specifying the length in bytes) from the start of the file. If Pointer is the atom end_of_file the current position is moved to the end of the file. Hence a file could be open in append mode using
open(File, update, Stream), seek(Stream, end_of_file)
The current position in a file may be found by the predicate at/2. The call
at(Stream, Pointer)
unifies Pointer with the current position in the file. The predicate
at_eof(Stream)
succeeds if the current position in the given stream is at the file end.


next up previous index
Next: In-memory Streams Up: Input and Output Previous: Opening New Streams   Index

1999-08-06