Common Lisp the Language, 2nd Edition
Next: RenamingDeleting, and
Up: File System Interface
Previous: Pathname
Functions
When a file is opened, a stream object is constructed to
serve as the file system’s ambassador to the Lisp environment;
operations on the stream are reflected by operations on the file in the
file system. The act of closing the file (actually, the stream)
ends the association; the transaction with the file system is
terminated, and input/output may no longer be performed on the stream.
The stream function close
may be used to close a file; the
functions described below may be used to open them. The basic operation
is open
, but with-open-file
is usually more
convenient for most applications.
[Function]
open
filename
&key :direction :element-type :if-exists :if-does-not-exist :external-format
X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to add to the
function open
a new keyword argument
:external-format
. This argument did not appear in the
preceding argument description in the first edition.
This returns a stream that is connected to the file specified by filename. The filename is the name of the file to be opened; it may be a string, a pathname, or a stream. (If the filename is a stream, then it is not closed first or otherwise affected; it is used merely to provide a file name for the opening of a new stream.)
X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result
of open
, if it is a stream, is always a stream of type
file-stream
.
X3J13 voted in March 1988 (PATHNAME-STREAM) to specify exactly which streams may be used as pathnames. See section 23.1.6.
X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify
that open
is unaffected by whether the first argument, if a
stream, is open or closed. If the first argument is a stream,
open
behaves as if the function pathname
were
applied to the stream and the resulting pathname used instead.
X3J13 voted in June 1989 (PATHNAME-WILD) to clarify that
open
accepts only non-wild pathnames; an error is signaled
if wild-pathname-p
would be true of filename.
X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require
open
to accept logical pathnames (see section 23.1.5).
The keyword arguments specify what kind of stream to produce and how to handle errors:
:direction
This argument specifies whether the stream should handle input, output,
or both.
:input
The result will be an input stream. This is the default.
:output
The result will be an output stream.
:io
The result will be a bidirectional stream.
:probe
The result will be a no-directional stream (in effect, the stream is created and then closed). This is useful for determining whether a file exists without actually setting up a complete stream.
:element-type
This argument specifies the type of the unit of transaction for the
stream. Anything that can be recognized as being a finite subtype of
character
or integer
is acceptable. In
particular, the following types are recognized:
string-char
The unit of transaction is a string-character. The functionsread-char
and/orwrite-char
may be used on the stream. This is the default.
character
The unit of transaction is any character, not just a string-character. The functionsread-char
and/orwrite-char
may be used on the stream.
X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to eliminate the
type string-char
, add the type base-character
,
and redefine open
to use the type character
as
the default :element-type
.
The preceding two possibilities should therefore be replaced by the following.
character
The unit of transaction is any character, not just a string-character. The functionsread-char
andwrite-char
(depending on the value of the:direction
argument) may be used on the stream. This is the default.
base-character
The unit of transaction is a base character. The functionsread-char
andwrite-char
(depending on the value of the:direction
argument) may be used on the stream.
(unsigned-byte
n
)
The unit of transaction is an unsigned byte (a non-negative integer) of size n. The functionsread-byte
and/orwrite-byte
may be used on the stream.
unsigned-byte
The unit of transaction is an unsigned byte (a non-negative integer); the size of the byte is determined by the file system. The functionsread-byte
and/orwrite-byte
may be used on the stream.
(signed-byte
n
)
The unit of transaction is a signed byte of size n. The functionsread-byte
and/orwrite-byte
may be used on the stream.
signed-byte
The unit of transaction is a signed byte; the size of the byte is determined by the file system. The functionsread-byte
and/orwrite-byte
may be used on the stream.
bit
The unit of transaction is a bit (values0
and1
). The functionsread-byte
and/orwrite-byte
may be used on the stream.
(mod
n
)
The unit of transaction is a non-negative integer less than n. The functionsread-byte
and/orwrite-byte
may be used on the stream.
:default
The unit of transaction is to be determined by the file system, based on the file it finds. The type can be determined by using the functionstream-element-type
.
:if-exists
This argument specifies the action to be taken if the
:direction
is :output
or :io
and
a file of the specified name already exists. If the direction is
:input
or :probe
, this argument is
ignored.
:error
Signals an error. This is the default when the version component of the filename is not:newest
.
:new-version
Creates a new file with the same file name but with a larger version number. This is the default when the version component of the filename is:newest
.
:rename
Renames the existing file to some other name and then creates a new file with the specified name.
:rename-and-delete
Renames the existing file to some other name and then deletes it (but does not expunge it, on those systems that distinguish deletion from expunging). Then create a new file with the specified name.
:overwrite
Uses the existing file. Output operations on the stream will destructively modify the file. If the:direction
is:io
, the file is opened in a bidirectional mode that allows both reading and writing. The file pointer is initially positioned at the beginning of the file; however, the file is not truncated back to length zero when it is opened. This mode is most useful when thefile-position
function can be used on the stream.
:append
Uses the existing file. Output operations on the stream will destructively modify the file. The file pointer is initially positioned at the end of the file. If the:direction
is:io
, the file is opened in a bidirectional mode that allows both reading and writing.
:supersede
Supersedes the existing file. If possible, the implementation should arrange not to destroy the old file until the new stream is closed, against the possibility that the stream will be closed in ``abort’’ mode (seeclose
). This differs from:new-version
in that:supersede
creates a new file with the same name as the old one, rather than a file name with a higher version number.
nil
Does not create a file or even a stream, but instead simply returnsnil
to indicate failure.
If the :direction
is :output
or
:io
and the value of :if-exists
is
:new-version
, then the version of the (newly created) file
that is opened will be a version greater than that of any other file in
the file system whose other pathname components are the same as those of
filename.
If the :direction
is :input
or
:probe
or the value of :if-exists
is not
:new-version
, and the version component of the
filename is :newest
, then the file opened is that
file already existing in the file system that has a version greater than
that of any other file in the file system whose other pathname
components are the same as those of filename.
Some file systems permit yet other actions to be taken when a file
already exists; therefore, some implementations provide
implementation-specific :if-exist
options.
Implementation note: The various file systems in existence today have widely differing capabilities. A given implementation may not be able to support all of these options in exactly the manner stated. An implementation is required to recognize all of these option keywords and to try to do something ``reasonable’’ in the context of the host operating system. Implementors are encouraged to approximate the semantics specified here as closely as possible.
As an example, suppose that a file system does not support distinct
file versions and does not distinguish the notions of deletion and
expunging (in some file systems file deletion is reversible until an
expunge operation is performed). Then :new-version
might be
treated the same as :rename
or :supersede
, and
:rename-and-delete
might be treated the same as
:supersede
.
If it is utterly impossible for an implementation to handle some option in a manner close to what is specified here, it may simply signal an error. The opening of files is an area where complete portability is too much to hope for; the intent here is simply to make things as portable as possible by providing specific names for a range of commonly supportable options.
:if-does-not-exist
This argument specifies the action to be taken if a file of the
specified name does not already exist.
:error
Signals an error. This is the default if the:direction
is:input
, or if the:if-exists
argument is:overwrite
or:append
.
:create
Creates an empty file with the specified name and then proceeds as if it had already existed (but do not perform any processing directed by the:if-exists
argument). This is the default if the:direction
is:output
or:io
, and the:if-exists
argument is anything but:overwrite
or:append
.
nil
Does not create a file or even a stream, but instead simply returnsnil
to indicate failure. This is the default if the:direction
is:probe
.
X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to add to the
function open
a new keyword argument
:external-format
.
:external-format
This argument specifies an implementation-recognized scheme for
representing characters in files. The default value is
:default
and is implementation-defined but must support the
base characters. An error is signaled if the implementation does
recognize the specified format.
This argument may be specified if the :direction
argument is :input
, :output
, or
:io
. It is an error to write a character to the resulting
stream that cannot be represented by the specified file format.
(However, the #\Newline
character cannot produce such an
error; implementations must provide appropriate line division behavior
for all character streams.)
See stream-external-format
.
When the caller is finished with the stream, it should close the file
by using the close
function. The
with-open-file
form does this automatically, and so is
preferred for most purposes. open
should be used only when
the control structure of the program necessitates opening and closing of
a file in some way more complex than provided by
with-open-file
. It is suggested that any program that uses
open
directly should use the special form
unwind-protect
to close the file if an abnormal exit
occurs.
[Macro]
with-open-file (stream filename {options}*)
{declaration}* {form}*
with-open-file
evaluates the forms of the body
(an implicit progn
) with the variable stream bound
to a stream that reads or writes the file named by the value of
filename. The options are evaluated and are used as
keyword arguments to the function open
.
When control leaves the body, either normally or abnormally (such as
by use of throw
), the file is automatically closed. If a
new output file is being written, and control leaves abnormally, the
file is aborted and the file system is left, so far as possible, as if
the file had never been opened. Because with-open-file
always closes the file, even when an error exit is taken, it is
preferred over open
for most applications.
filename is the name of the file to be opened; it may be a string, a pathname, or a stream.
X3J13 voted in March 1988 (PATHNAME-STREAM) to specify exactly which
streams may be used as pathnames. See section 23.1.6.
X3J13 voted in June 1989 (PATHNAME-WILD) to clarify that
with-open-file
accepts only non-wild pathnames; an error is
signaled if wild-pathname-p
would be true of the
filename argument.
X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require
with-open-file
to accept logical pathnames (see section 23.1.5).
For example:
(with-open-file (ifile name
:direction :input)
(with-open-file (ofile (merge-pathname-defaults ifile
nil
"out")
:direction :output
:if-exists :supersede)
(transduce-file ifile ofile)))
X3J13 voted in June 1989 (WITH-OPEN-FILE-DOES-NOT-EXIST) to specify
that the variable stream is not always bound to a stream;
rather it is bound to whatever would be returned by a call to
open
. For example, if the options include
:if-does-not-exist nil
, stream will be bound to
nil
if the file does not exist. In this case the value of
stream should be tested within the body of the
with-open-file
form before it is used as a stream. For
example:
(with-open-file (ifile name
:direction :input
:if-does-not-exist nil)
;; Process the file only if it actually exists.
(when (streamp name)
(compile-cobol-program ifile)))
Implementation note: While
with-open-file
tries to automatically close the stream on
exit from the construct, for robustness it is helpful if the garbage
collector can detect discarded streams and automatically close them.
Next: RenamingDeleting, and
Up: File System Interface
Previous: Pathname
Functions
AI.Repository@cs.cmu.edu