User Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cl:functions:open [2019/07/14 17:00]
cl:functions:open [2019/07/17 21:00] (current)
Line 1: Line 1:
 +====== 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}