File Input and Output

Arity/Prolog32 provides handle-based file operations and also a style of redirecting input and output based on the see/seeing/seen and tell/telling/told patterns.

Many of the input and output predicates use standard input or standard output as an implicit argument. For example, read/1 is the same as read/2 except that it always operates on standard input. While standard input and standard output may be redirected, it is common to use them for keyboard and display interactions. Input and output predicates that take a handle argument may use standard input and standard output by specifying handles 0 and 1, respectively.

This section describes predicates for performing these file operations. As an example, using file input and output we can write a very simple predicate to copy one file to another. The copy predicate below places the open and close operations outside of a repeat-fail loop. Within the loop, it calls a second predicate, movechar/2, to read and write one character at a time from one file to the other. This is done with the get0/2 and put/2 predicates. When the end of file is reached, get0/2 fails and the repeat/fail loop of copy terminates.

copy(X,Y) :-
    open(H1,X,r),
    create(H2,Y),
    repeat,
        movechar(H1,H2),    % succeeds when done
    !,
    close(H1),
    close(H2).

movechar(H1,H2) :-
    get0(H1,C),
    !,
    put(H2,C),
    fail.
movechar(_,_).

Opening and closing files

create(-Handle,+Filename)

You use the create/2 predicate to create and open a new file.

open(-Handle,+Filename,+Access)

You use the open/3 predicate to open an existing file. If Filename is a file name without a path, then the system attempts to open the specified file in the current directory - if the file can not be found in the current directory, the open predicate will fail.

The access mode argument can be one of the following atoms:

atommeaning
rread only
wwrite
aappend
rwread or write
raread or append

p_open(-Handle,+Filename,+Access)

p_open(-Handle,+Filename,+Access,+Path)

As with open, you use the p_open/3 or p_open/4 predicate to open an existing file. The p_open/4 predicate uses the supplied Path to find the file specified by Filename. The p_open/3 predicate will search for the file. following this sequence:

1 The system first looks for the file in the current directory. 1 The system next looks for the file in the directory in which the executable file (exe) for the current application resides. 1 The system will next search for the file as per the path defined by the environment variable PathVar, such as $PATH$ or $INCLUDE$. If no PathVar was specified, then it is assumed to be $PATH$.

If none of the searches are successful, the p_open/3 predicate fails.

close(+Handle)

The close/1 predicate closes a file. You specify the file that you want to close by supplying its Handle, not its file specification.

Locating a file

searchPath(+PathSpec,+FileSpec,+Flags,-CompleteFileSpec)

The searchPath/4 predicate searches for a file along the path specified by PathSpec for files that match FileSpec.

PathSpec may be an environment variable or directories separated by semicolons. FileSpec can be either a name or have wild card characters, such as 'ARITY.HLP' or '*.hlp'. Flags is an integer that described how the search is performed and/or how to interpret the PathSpec variable, which is a sum of the one or more of the following values:

1 (search the current directory)

2 (PathSpec is an environment variable)

4 (search the application directory)

The if searchPath/4 succeeds, CompleteFileSpec is the file that was found.

File position seeking

For each open file an internal pointer is maintained which keeps track of your current position. When you open a file, this pointer is initially set to either the beginning or the end of the file, depending on the access mode you have specified. The pointer is moved when you add information to the file, when you read from the file, or when you reposition the pointer with seek/4.

seek(+Handle,+Offset,+Method,-NewLoc)

The seek/4 predicate is useful for randomly accessing a portion of a file.

**seek/4 takes the file handle, an offset, a starting location, and an uninstantiated variable as arguments. The Method and Offset arguments define the new location as a byte offset from either the beginning, end, or current position within the file. The Method argument gives the starting point from which to calculate the new location, as one of the following atoms:

bof

Offset is calculated from the beginning of the file.

eof

Offset is calculated from the end of the file.

current

Offset is calculated from your current location.

The Offset argument represents a relative location within the file in bytes. The offset is always zero-based. That is, you can reach the beginning of the file at offset 0 from bof; the end of file at offset 0 from eof; and your current position at offset 0 from current. The relative location is expressed as an integer. Therefore, the offset must be within the range of -2,147,483,648 and 2,147,483,647.

seek/4 returns the new location to the NewLoc argument.

Redirecting standard input and output

stdin(+Filename,+Goal)

stdout(+Filename,+Goal)

stdinout(+InFile,+OutFile,+Goal)

The stdin/2, stdout/2, and stdinout/3 predicates redirect the standard input or standard output devices, or both, for the duration of a goal. When the goal completes, these devices are restored to their original values. If any of these predicates are used in a compiled program, then the Goal must be made visible.

If you send output to an existing file, the output overwrites whatever is currently in the file. Note that stdin/2, stdout/2, and **stdinout/3 do not recognize any default file name extensions.

Redirecting standard input or output is often convenient for simple programs or for testing. It is generally not a good technique for larger programs.

Standard Prolog file input and output

It is recommended that you use the Input/Output predicates described above to read from and write to files. They are more efficient and versatile. However, some Prolog implementations use the predicates descibed below to read from and write to files. Arity/Prolog32 provides these predicates so that any existing programs containing these predicates can be run without any changes to the file Input/Output.

see(+Filename)

The see/1 predicate opens the file supplied as Filename for reading if it is not already open.

Input is read from this file until one of the following occurs:

  • The file is closed for reading using the seen predicate.
  • Another file is opened for reading using the see predicate. In this instance, input is read from the newly opened file.

The file input starts at the beginning of the file when it is first opened. If a file has been previously opened using see (and is not closed using seen), and then is accessed again using see, then file input starts from the point from which it was left. The Filename must be an existing file.

seeing(-Filename)

The seeing/1 predicate returns the name of the file that is currently open for reading if the file was opened for reading using the see predicate. If the file was not opened using the see predicate, then seeing fails.

For example, if the file named rule1 was opened for reading using the see command, then the seeing command would return the following:

?- seeing(X)
X = rule1
yes

seen

The seen/0 predicate ends input from the current open file and closes the file. Subsequent input is taken from the keyboard.

see_h(+Handle)

The see_h/1 predicate is for reading from a file which has previously been open for reading using the open predicate. The Handle is the handle of the opened file as returned by the open predicate.

tell(+Filename)

The tell/1 predicate opens the file supplied as Filename for writing.

When a file is opened using tell, all output will be sent to that file until one of the following occurs:

  • The file is closed for writing using the told predicate.
  • Another file is opened for writing using the tell predicate.

If Filename is the name of a file that does not exist, then tell creates a new file with that name. If Filename is the name of a file that exists and is not yet open, then the file is opened and the contents of the file are destroyed and are replaced by the new output. If Filename is the name of a file that has previously been opened using tell and has not been closed using told, then any new output is appended to the existing file.

telling(-Filename)

The telling/1 predicate returns the name of the file that is currently opened for writing if the file was opened for writing using the tell predicate. If the file was not opened using the tell predicate, then telling fails.

told

The told/0 predicate closes the file that is currently open for writing. An end-of-file marker is written to the file. Subsequent output is sent to the display.

tell_h(+Handle)

The tell_h/1 predicate is for writing to a file that has previously been open for writing using the open or create predicates. The Handle is the handle of the opened file as returned by the open predicate. When the tell_h/1 predicate is used, all output will be sent to the file specified by Handle until it is closed using the told predicate. The current contents of the file are overwritten by the output sent to the file as a result of using tell_h/1.