User Tools


====== Function OPEN ====== ====Syntax==== * **open** //filespec// ''&key'' //direction// //element-type// //if-exists// //if-does-not-exist// //external-format// → //stream// ====Arguments and Values==== * //filespec// - a //[[CL:Glossary:pathname designator]]//. * //direction// - one of **'':input''**, **'':output''**, **'':io''**, or **'':probe''**. The default is **'':input''**. * //element-type// - a //[[CL:Glossary:type specifier]]// for //[[CL:Glossary:recognizable subtype]]// of **[[CL:Types:character]]**; or a //[[CL:Glossary:type specifier]]// for a //[[CL:Glossary:finite]]// //[[CL:Glossary:recognizable subtype]]// of //[[CL:Glossary:integer]]//; or one of the //[[CL:Glossary:symbols]]// **[[CL:Types:signed-byte]]**, **[[CL:Types:unsigned-byte]]**, or **'':default''**. The default is **[[CL:Types:character]]**. * //if-exists// - one of **'':error''**, **'':new-version''**, **'':rename''**, **'':rename-and-delete''**, **'':overwrite''**, **'':append''**, **'':supersede''**, or **[[CL:Constant Variables:nil]]**. The default is **'':new-version''** if the version component of //filespec// is **'':newest''**, or **'':error''** otherwise. * //if-does-not-exist// - one of **'':error''**, **'':create''**, or **[[CL:Constant Variables:nil]]**. The default is **'':error''** if //direction// is **'':input''** or //if-exists// is **'':overwrite''** or **'':append''**; **'':create''** if //direction// is **'':output''** or **'':io''**, and //if-exists// is neither **'':overwrite''** nor **'':append''**; or **[[CL:Constant Variables:nil]]** when //direction// is **'':probe''**. * //external-format// - an //[[CL:Glossary:external file format designator]]//. The default is **'':default''**. * //stream// - a //[[CL:Glossary:file stream]]// or **[[CL:Constant Variables:nil]]**. ====Description==== **open** creates, opens, and returns a //[[CL:Glossary:file stream]]// that is connected to the file specified by //filespec//. //Filespec// is the name of the file to be opened. If the //filespec// //[[CL:Glossary:designator]]// is a //[[CL:Glossary:stream]]//, that //[[CL:Glossary:stream]]// is not closed first or otherwise affected. The keyword arguments to **open** specify the characteristics of the //[[CL:Glossary:file stream]]// that is returned, and how to handle errors. If //direction// is **'':input''** or **'':probe''**, or if //if-exists// is not **'':new-version''** and the version component of the //filespec// 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 //filespec//. An implementation is required to recognize all of the **open** keyword options and to do something reasonable in the context of the host operating system. For example, if a file system does not support distinct file versions and does not distinguish the notions of deletion and expunging, **'':new-version''** might be treated the same as **'':rename''** or **'':supersede''**, and **'':rename-and-delete''** might be treated the same as **'':supersede''**. ===:direction=== These are the possible values for //direction//, and how they affect the nature of the //[[CL:Glossary:stream]]// that is created: * **'':input''**: Causes the creation of an //[[CL:Glossary:input]]// //[[CL:Glossary:file stream]]//. * **'':output''**: Causes the creation of an //[[CL:Glossary:output]]// //[[CL:Glossary:file stream]]//. * **'':io''**: Causes the creation of a //[[CL:Glossary:bidirectional]]// //[[CL:Glossary:file stream]]//. * **'':probe''**: Causes the creation of a "no-directional" //[[CL:Glossary:file stream]]//; in effect, the //[[CL:Glossary:file stream]]// is created and then closed prior to being returned by **open**. ===:element-type=== The //element-type// specifies the unit of transaction for the //[[CL:Glossary:file stream]]//. If it is **'':default''**, the unit is determined by //[[CL:Glossary:file system]]//, possibly based on the //[[CL:Glossary:file]]//. ===:if-exists=== //if-exists// specifies the action to be taken if //direction// is **'':output''** or **'':io''** and a file of the name //filespec// already exists. If //direction// is **'':input''**, not supplied, or **'':probe''**, //if-exists// is ignored. These are the results of **open** as modified by //if-exists//: * **'':error''**: An error of type **[[CL:Types:file-error]]** is signaled. * **'':new-version''**: A new file is created with a larger version number. * **'':rename''**: The existing file is renamed to some other name and then a new file is created. * **'':rename-and-delete''**: The existing file is renamed to some other name, then it is deleted but not expunged, and then a new file is created. * **'':overwrite''**: Output operations on the //[[CL:Glossary:stream]]// destructively modify the existing file. If //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. * **'':append''**: Output operations on the //[[CL:Glossary:stream]]// destructively modify the existing file. The file pointer is initially positioned at the end of the file. If //direction// is **'':io''**, the file is opened in a bidirectional mode that allows both reading and writing. * **'':supersede''**: The existing file is superseded; that is, a new file with the same name as the old one is created. If possible, the implementation should not destroy the old file until the new //[[CL:Glossary:stream]]// is closed. * **[[CL:Constant Variables:nil]]**: No file or //[[CL:Glossary:stream]]// is created; instead, **[[CL:Constant Variables:nil]]** is returned to indicate failure. ===:if-does-not-exist=== //if-does-not-exist// specifies the action to be taken if a file of name //filespec// does not already exist. These are the results of **open** as modified by //if-does-not-exist//: * **'':error''**: An error of type **[[CL:Types:file-error]]** is signaled. * **'':create''**: An empty file is created. Processing continues as if the file had already existed but no processing as directed by //if-exists// is performed. * **[[CL:Constant Variables:nil]]**: No file or //[[CL:Glossary:stream]]// is created; instead, **[[CL:Constant Variables:nil]]** is returned to indicate failure. ===:external-format=== This option selects an //[[CL:Glossary:external file format]]// for the //[[CL:Glossary:file]]//: The only //[[CL:Glossary:standardized]]// value for this option is **'':default''**, although //[[CL:Glossary:implementation|implementations]]// are permitted to define additional //[[CL:Glossary:external file formats]]// and //[[CL:Glossary:implementation-dependent]]// values returned by **[[CL:Functions:stream-external-format]]** can also be used by //[[CL:Glossary:conforming program|conforming programs]]//. The //external-format// is meaningful for any kind of //[[CL:Glossary:file stream]]// whose //[[CL:Glossary:element type]]// is a //[[CL:Glossary:subtype]]// of //[[CL:Glossary:character]]//. This option is ignored for //[[CL:Glossary:stream|streams]]// for which it is not meaningful; however, //[[CL:Glossary:implementation|implementations]]// may define other //[[CL:Glossary:element types]]// for which it is meaningful. The consequences are unspecified if a //[[CL:Glossary:character]]// is written that cannot be represented by the given //[[CL:Glossary:external file format]]//. ------- When a file is opened, a //[[CL:Glossary:file stream]]// is constructed to serve as the file system's ambassador to the Lisp environment; operations on the //[[CL:Glossary:file stream]]// are reflected by operations on the file in the file system. A file can be deleted, renamed, or destructively modified by **open**. For information about opening relative pathnames, see section {\secref\MergingPathnames}. ====Examples==== <blockquote> ;;; TODO these examples are more or less useless (open //filespec// :direction :probe) <r>#<Closed Probe File Stream...> </r> ([[CL:Macros:defparameter]] *q* ([[CL:Functions:merge-pathnames]] ([[CL:Functions:user-homedir-pathname]]) "test")) <r>*Q*</r> *q* <r>#<PATHNAME :HOST [[CL:Constant Variables:NIL]] :DEVICE //device-name// :DIRECTORY //directory-name// :NAME "test" :TYPE [[CL:Constant Variables:NIL]] :VERSION :NEWEST></r> (open //filespec// :if-does-not-exist :create) <r>#<Input File Stream...> </r> ([[CL:Macros:defparameter]] *s* (open //filespec// :direction :probe)) <r>*S*</r> *s* <r>#<Closed Probe File Stream...> </r> ([[CL:Functions:truename]] *s*) #<PATHNAME :HOST [[CL:Constant Variables:NIL]] :DEVICE //device-name// :DIRECTORY //directory-name// :NAME //filespec// :TYPE //extension// :VERSION 1> (open s :direction :output :if-exists [[CL:Constant Variables:nil]]) <r>[[CL:Constant Variables:NIL]]</r> </blockquote> ====Affected By==== The nature and state of the host computer's //[[CL:Glossary:file system]]//. ====Exceptional Situations==== If //if-exists// is **'':error''**, (subject to the constraints on the meaning of //if-exists// listed above), an error of type **[[CL:Types:file-error]]** is signaled. If //if-does-not-exist// is **'':error''** (subject to the constraints on the meaning of //if-does-not-exist// listed above), an error of type **[[CL:Types:file-error]]** is signaled. If it is impossible for an implementation to handle some option in a manner close to what is specified here, an error of type **[[CL:Types:error]]** might be signaled. An error of type **[[CL:Types:file-error]]** is signaled if **[[CL:Functions:(wild-pathname-p //filespec//)]]** returns true. An error of type **[[CL:Types:error]]** is signaled if the //external-format// is not understood by the //[[CL:Glossary:implementation]]//. The various //[[CL:Glossary:file systems]]// in existence today have widely differing capabilities, and some aspects of the //[[CL:Glossary:file system]]// are beyond the scope of this specification to define. A given //[[CL:Glossary:implementation]]// might not be able to support all of these options in exactly the manner stated. An //[[CL:Glossary:implementation]]// is required to recognize all of these option keywords and to try to do something "reasonable" in the context of the host //[[CL:Glossary:file system]]//. Where necessary to accomodate the //[[CL:Glossary:file system]]//, an //[[CL:Glossary:implementation]]// deviate slightly from the semantics specified here without being disqualified for consideration as a //[[CL:Glossary:conforming implementation]]//. If it is utterly impossible for an //[[CL:Glossary:implementation]]// to handle some option in a manner similar to what is specified here, it may simply signal an error. With regard to the **'':element-type''** option, if a //[[CL:Glossary:type]]// is requested that is not supported by the //[[CL:Glossary:file system]]//, a substitution of types such as that which goes on in //[[CL:Glossary:upgrade|upgrading]]// is permissible. As a minimum requirement, it should be the case that opening an //[[CL:Glossary:output]]// //[[CL:Glossary:stream]]// to a //[[CL:Glossary:file]]// in a given //[[CL:Glossary:element type]]// and later opening an //[[CL:Glossary:input]]// //[[CL:Glossary:stream]]// to the same //[[CL:Glossary:file]]// in the same //[[CL:Glossary:element type]]// should work compatibly. ====See Also==== * **[[CL:Macros:with-open-file|Macro WITH-OPEN-FILE]]** * **[[CL:Functions:close|Function CLOSE]]** * **[[CL:Types:pathname|System Class PATHNAME]]** * **[[CL:Types:logical-pathname|System Class LOGICAL-PATHNAME]]** * {\secref\MergingPathnames} * {\secref\PathnamesAsFilenames} ====Notes==== **open** does not automatically close the file when an abnormal exit occurs. When //element-type// is a //[[CL:Glossary:subtype]]// of **[[CL:Types:character]]**, **[[CL:Functions:read-char]]** and/or **[[CL:Functions:write-char]]** can be used on the resulting //[[CL:Glossary:file stream]]//. When //element-type// is a //[[CL:Glossary:subtype]]// of //[[CL:Glossary:integer]]//, **[[CL:Functions:read-byte]]** and/or **[[CL:Functions:write-byte]]** can be used on the resulting //[[CL:Glossary:file stream]]//. When //element-type// is **'':default''**, the //[[CL:Glossary:type]]// can be determined by using **[[CL:Functions:stream-element-type]]**. \issue{CHARACTER-PROPOSAL:2-5-2} \issue{STREAM-ACCESS:ADD-TYPES-ACCESSORS} \issue{CHARACTER-PROPOSAL:2-5-2} \issue{PATHNAME-WILD:NEW-FUNCTIONS} \issue{CHARACTER-PROPOSAL:2-5-2} \issue{PATHNAME-LOGICAL:ADD} \issue{FILE-OPEN-ERROR:SIGNAL-FILE-ERROR} \issue{PATHNAME-HOST-PARSING:RECOGNIZE-LOGICAL-HOST-NAMES}