SWI-Prolog provides two different packages for input and output. The native I/O system is based on the ISO standard predicates open/3, close/1 and friends. (26) Being more widely portable and equiped with a clearer and more robust specification, new code is encouraged to use these predicates for manipulation of I/O streams.
Section 4.16.2 describes tell/1, see/1 and friends, providing I/O in the spirit of the outdated Edinburgh standard. These predicates are layered on top of the ISO predicates. Both packages are fully integrated; the user may switch freely between them.
The predicates described in this section provide ISO compliant I/O, where 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.
This schema is not vulnerable to filename and stream ambiguities as well as changes to the working directory. New code is adviced to use these predicates to manage input and output streams.
pipe(Command)
',
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. 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. (27)
The Options list can contain the following options:
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.
?- open(data, read, Fd, [alias(input)]). ..., read(input, Term), ... |
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.
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.
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).
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.
/dev/null
.
Stream can be an atom, giving the null-stream an alias name.
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.
read
, write
, append
and the SWI-Prolog extension update
.
read
.
write
, append
or
update
.
$stream_position(CharIndex,
LineNo, LinePos)
. See also set_stream_position/2.
not
, at
or past
. See
also
at_end_of_stream/[0,1].
eof_code
, reset
or
error
. See open/4
for details.
text
or binary
.
SWI-Stream.h
.
full
, line
or false
.
See also open/4.
if the
stream refers to some other object.
Mode is one of read
or write
.
position(Pos)
property. See also seek/4.
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_property/2
and set_stream_position/2.
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.
full
, line
or false
.
eof_code
, reset
or
error
.
error(timeout_error(read, Stream)
, _)
The package for implicit input and output destination is (almost) compatible to Edinburgh 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.
Source and destination are either a file, user
, or a
term `pipe(Command)'. The reserved stream name user
refers to the terminal. (29)
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). | % Start writing to the terminal. |
?- 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([]). |
Unlike Edinburgh Prolog systems, telling/1 and seeing/1 do not return the filename of the current input/output, but the stream-identifier, to ensure the design pattern below works under all circumstances. (30)
..., telling(Old), tell(x), ..., told, tell(Old), ..., |
The predicates tell/1
and see/1 first
check for user
, the
pipe(command)
and a stream-handle. Otherwise, if the
argument is an atom it is first compared to open streams associated to a
file with exactly the same name. If such a stream, created
using
tell/1 or see/1
exists, output (input) is switch to the open stream. Otherwise a file
with the specified name is opened.
The behaviour is compatible to Edinburgh Prolog. This is not without problems. Changing directory, non-file streams, multiple names referring to the same file easily lead to unexpected behaviour. New code, especially when managing multiple I/O channals should consider using the ISO I/O predicates defined in section 4.16.1.
user
is returned if the current input is the
stream user_input
to improve compatibility with traditional
Edinburgh I/O. See the introduction of
section 4.16.2 for details.
user
is returned if the current output is the
stream user_output
to improve compatibility with
traditional Edinburgh I/O. See the introduction of
section 4.16.2 for details.
The predicates below can be used for switching between the implicit- and the explicit stream based I/O predicates.