Home Contents Index Summary Previous Next

3.16 Input and output

SWI-Prolog provides two different packages for input and output. One confirms to the Edinburgh standard. This package has a notion of `current-input' and `current-output'. The reading and writing predicates implicitly refer to these streams. In the second package, streams are opened explicitly and the resulting handle is used as an argument to the reading and writing predicate to specify the source or destination. Both packages are fully integrated; the user may switch freely between them.

3.16.1 Input and output using implicit source and destination

The package for implicit input and output destination is upwards compatible to DEC-10 and C-Prolog. The reading and writing predicates refer to resp. the current input- and output stream. Initially these streams are connected to the terminal. The current output stream is changed using tell/1 or append/1. The current input stream is changed using see/1. The streams current value can be obtained using telling/1 for output- and seeing/1 for input streams. The table below shows the valid stream specifications. The reserved names user_input, user_output and user_error are for neat integration with the explicit streams.

user This reserved name refers to the terminal
user_input Input from the terminal
user_output Output to the terminal
user_error Unix error stream (output only)
<Atom> Name of a Unix file
pipe(<Atom>) Name of a Unix command

Source and destination are either a file, one of the reserved words above, or a term `pipe(Command)'. In the predicate descriptions below we will call the source/destination argument `SrcDest'. Below are some examples of source/destination specifications.

?- see(data). % Start reading from file `data'.
?- tell(user_error). % Start writing on the error stream.
?- tell(pipe(lpr)). % Start writing to the printer.

Another example of using the pipe/1 construct is shown below. Note that the pipe/1 construct is not part of Prolog's standard I/O repertoire.


getwd(Wd) :-
        seeing(Old), see(pipe(pwd)), 
        collect_wd(String), 
        seen, see(Old), 
        atom_codes(Wd, String).

collect_wd([C|R]) :-
        get0(C), C \== -1, !, 
        collect_wd(R).
collect_wd([]).

see(+SrcDest)
Make SrcDest the current input stream. If SrcDest was already opened for reading with see/1 and has not been closed since, reading will be resumed. Otherwise SrcDest will be opened and the file pointer is positioned at the start of the file.

tell(+SrcDest)
Make SrcDest the current output stream. If SrcDest was already opened for writing with tell/1 or append/1 and has not been closed since, writing will be resumed. Otherwise the file is created or---when existing---truncated. See also append/1.

append(+File)
Similar to tell/1, but positions the file pointer at the end of File rather than truncating an existing file. The pipe construct is not accepted by this predicate.

seeing(?SrcDest)
Unify the name of the current input stream with SrcDest.

telling(?SrcDest)
Unify the name of the current output stream with SrcDest.

seen
Close the current input stream. The new input stream becomes user.

told
Close the current output stream. The new output stream becomes user.

3.16.2 Explicit Input and Output Streams

The predicates below are part of the Quintus compatible stream-based I/O package. In this package streams are explicitly created using the predicate open/3. The resulting stream identifier is then passed as a parameter to the reading and writing predicates to specify the source or destination of the data.

open(+SrcDest, +Mode, -Stream, +Options)
ISO compliant predicate to open a stream. SrcDes is either an atom, specifying a Unix file, or a term `pipe(Command)', just like see/1 and tell/1. Mode is one of read, write, append or update. Mode append opens the file for writing, positioning the file-pointer at the end. Mode update opens the file for writing, positioning the file-pointer at the beginning of the file without truncating the file. See also stream_position/3. Stream is either a variable, in which case it is bound to an integer identifying the stream, or an atom, in which case this atom will be the stream identifier. The Options list can contain the following options:

type(Type)
Using type text (default), Prolog will write a text-file in an operating-system compatible way. Using type binary the bytes will be read or written without any translation. Note there is no difference between the two on Unix systems.

alias(Atom)
Gives the stream a name. Below is an example. Be careful with this option as stream-names are global. See also set_stream/2.


?- open(data, read, Fd, [alias(input)]).

        ...,
        read(input, Term),
        ...

eof_action(Action)
Defines what happens if the end of the input stream is reached. Action eof_code makes get0/1 and friends return -1 and read/1 and friends return the atom end_of_file. Repetitive reading keeps yielding the same result. Action error is like eof_code, but repetitive reading will raise an error. With action reset, Prolog will examine the file again and return more data if the file has grown.

buffer(Buffering)
Defines output buffering. The atom full (default) defines full buffering, line buffering by line, and false implies the stream is fully unbuffered. Smaller buffering is useful if another process or the user is waiting for the output as it is being produced. See also flush_output/[0,1]. This option is not an ISO option.

close_on_abort(Bool)
If true (default), the stream is closed on an abort (see abort/0). If false, the stream is not closed. If it is an output stream, it will be flushed however. Useful for logfiles and if the stream is associated to a process (using the pipe/1 construct).

lock(LockingMode)
Try to obtain a lock on the open file. Default is none, which does not lock the file. The value read or shared means other processes may read the file, but not write it. The value write or exclusive means no other process may read or write the file.

Locks are acquired through the POSIX function fcntl() using the command F_SETLKW, which makes a blocked call wait for the lock to be released. Please note that fcntl() locks are advisory and therefore only other applications using the same advisory locks honour your lock. As there are many issues around locking in Unix, expecially related to NFS (network file system), please study the fcntl() manual page before trusting your locks!

The lock option is a SWI-Prolog extension.

The option reposition is not supported in SWI-Prolog. All streams connected to a file may be repositioned.

open(+SrcDest, +Mode, ?Stream)
Equivalent to open/4 with an empty option-list.

open_null_stream(?Stream)
Open a stream that produces no output. All counting functions are enabled on such a stream. An attempt to read from a null-stream will immediately signal end-of-file. Similar to Unix /dev/null. Stream can be an atom, giving the null-stream an alias name.

close(+Stream)
Close the specified stream. If Stream is not open an error message is displayed. If the closed stream is the current input or output stream the terminal is made the current input or output.

close(+Stream, +Options)
Provides close(Stream, [force(true)]) as the only option. Called this way, any resource error (such as write-errors while flushing the output buffer) are ignored.

stream_property(?Stream, ?StreamProperty)
ISO compatible predicate for querying status of open I/O streams. StreamProperty is one of:

file_name(Atom)
If Stream is associated to a file, unify Atom to the name of this file.

mode(IOMode)
Unify IOMode to the mode given to open/4 for opening the stream. Values are: read, write, append and the SWI-Prolog extension update.

input
True if Stream has mode read.

output
True if Stream has mode write, append or update.

alias(Atom)
If Atom is bound, test of the stream has the specified alias. Otherwise unify Atom with the first alias of the stream. (14)

position(Term)
Unify Term with the current stream-position. A stream-position is a term of format $stream_position(CharIndex, LineNo, LinePos). See also term_position/3.

end_of_stream(E)
If Stream is an input stream, unify E with one of the atoms not, at or past. See also at_end_of_stream/[0,1].

eof_action(A)
Unify A with one of eof_code, reset or error. See open/4 for details.

reposition(Bool)
Unify Bool with true if the position of the stream can be set (see seek/4). It is assumed the position can be set if the stream has a seek-function and is not based on a POSIX file-descriptor that is not associated to a regular file.

type(T)
Unify Bool with text or binary.

file_no(Integer)
If the stream is associated with a POSIX file-descriptor, unify Integer with the descriptor number. SWI-Prolog extension used primarily for integration with foreign code. See also Sfileno() from SWI-Stream.h.

buffer(Buffering)
SWI-Prolog extension to query the buffering mode of this stream. Buffering is one of full, line or false. See also open/4.

current_stream(?Object, ?Mode, ?Stream)
The predicate current_stream/3 is used to access the status of a stream as well as to generate all open streams. Object is the name of the file opened if the stream refers to an open file, an integer file-descriptor if the stream encapsulates an operating-system stream or the atom if the stream refers to some other object. Mode is one of read or write.

set_stream_position(+Stream, +Pos)
Set the current position of Stream to Pos. Pos is a term as returned by stream_property/2 using the position(Pos) property. See also seek/4.

seek(+Stream, +Offset, +Method, -NewLocation)
Reposition the current point of the given Stream. Method is one of bof, current or eof, indicating positioning relative to the start, current point or end of the underlying object. NewLocation is unified with the new offset, relative to the start of the stream.

If the seek modifies the current location, the line number and character position in the line are set to 0.

If the stream cannot be repostioned, a reposition error is raised. The predicate seek/4 is compatible to Quintus Prolog, though the error conditions and signalling is ISO compliant. See also stream_position/3.

set_stream(+Stream, +Attribute)
Modify an attribute of an existing stream. Attribute specifies the stream property to set. See also stream_property/2 and open/4.

alias(AliasName)
Set the alias of an already created stream. If AliasName is the name of one of the standard streams is used, this stream is rebound. Thus, set_stream(S, current_input) is the same as set_input/1 and by setting the alias of a stream to user_input, etc. all user terminal input is read from this stream. See also interactor/0.

buffer(Buffering)
Set the buffering mode of an already created stream. Buffering is one of full, line or false.

eof_action(Action)
Set end-of-file handling to one of eof_code, reset or error.

close_on_abort(Bool)
Determine whether or not the stream is closed by abort/0. By default streams are closed.

3.16.3 Switching Between Implicit and Explicit I/O

The predicates below can be used for switching between the implicit- and the explicit stream based I/O predicates.

set_input(+Stream)
Set the current input stream to become Stream. Thus, open(file, read, Stream), set_input(Stream) is equivalent to see(file).

set_output(+Stream)
Set the current output stream to become Stream.

current_input(-Stream)
Get the current input stream. Useful to get access to the status predicates associated with streams.

current_output(-Stream)
Get the current output stream.