User Tools


Differences

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

Link to this comparison view

cl:macros:with-open-file [2019/07/14 17:00]
cl:macros:with-open-file [2019/09/18 01:00] (current)
Line 1: Line 1:
 +====== Macro WITH-OPEN-FILE ======
 +
 +====Syntax====
 +  * **with-open-file** (//stream// //​filespec//​ //​options//''​*''​) //​declaration//''​*''​ //​form//''​*''​ → //results//
 +
 +====Arguments and Values====
 +//stream// -- a variable.
 +//​filespec//​ - a //​[[CL:​Glossary:​pathname designator]]//​.
 +//options// -- //​[[CL:​Glossary:​forms]]//;​ evaluated.
 +//​declaration//​ - a **[[CL:​Symbols:​declare]]** //​[[CL:​Glossary:​expression]]//;​ not evaluated.
 +//forms// - an //​[[CL:​Glossary:​implicit progn]]//.
 +//results// - the //​[[CL:​Glossary:​values]]//​ returned by the //forms//.
 +
 +====Description====
 +**with-open-file** uses **[[CL:​Functions:​open]]** to create a //​[[CL:​Glossary:​file stream]]// to //​[[CL:​Glossary:​file]]//​ named by //​filespec//​.
 +
 +//​filespec//​ is the name of the file to be opened. //options// are used as keyword arguments to **[[CL:​Functions:​open]]**.
 +
 +The //​[[CL:​Glossary:​stream]]//​ //​[[CL:​Glossary:​object]]//​ to which the //stream// //​[[CL:​Glossary:​variable]]//​ is //​[[CL:​Glossary:​bound]]//​ has //​[[CL:​Glossary:​dynamic extent]]//; its //​[[CL:​Glossary:​extent]]//​ ends when the //​[[CL:​Glossary:​form]]//​ is exited.
 +
 +**with-open-file** evaluates the //forms// as an //​[[CL:​Glossary:​implicit progn]]// with //stream// bound to the value returned by **[[CL:​Functions:​open]]**.
 +
 +When control leaves the body, either normally or abnormally (such as by use of **[[CL:​Special Operators:​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.
 +
 +It is possible by the use of '':​if-exists [[CL:​Constant Variables:​nil]]''​ or '':​if-does-not-exist [[CL:​Constant Variables:​nil]]''​ for //stream// to be bound to **[[CL:​Constant Variables:​nil]]**.
 +
 +Users of '':​if-does-not-exist [[CL:​Constant Variables:​nil]]''​ should check for a valid //​[[CL:​Glossary:​stream]]//​.
 +
 +The consequences are undefined if an attempt is made to //​[[CL:​Glossary:​assign]]//​ the //stream// //​[[CL:​Glossary:​variable]]//​. The compiler may choose to issue a warning if such an attempt is detected.
 +
 +====Examples====
 +<​blockquote>​
 +(setf *p* (merge-pathnames "​test"​))
 +<​r><​r>#<​PATHNAME :HOST [[CL:​Constant Variables:​NIL]] :DEVICE device-name :DIRECTORY directory-name
 +           :NAME "​test"​ :TYPE [[CL:​Constant Variables:​NIL]] :VERSION :​NEWEST></​r></​r>​
 +(with-open-file (s *p* :direction :output :if-exists :supersede)
 +   ​([[CL:​Functions:​format]] s "Here are a couple~%of test data lines~%"​)) ​
 +<​r>​[[CL:​Constant Variables:​NIL]]</​r>​
 +(with-open-file (s *p*)
 +   ​([[CL:​Macros:​do]] ((l ([[CL:​Functions:​read-line]] s) ([[CL:​Functions:​read-line]] s [[CL:​Constant Variables:​nil]] '​eof)))
 +       ​(([[CL:​Functions:​eq]] l 'eof) "​Reached end of file."​)
 +    ([[CL:​Functions:​format]] [[CL:​Constant Variables:​t]] "​~&​*** ~A~%" l)))
 +<​o>​*** Here are a couple
 +*** of test data lines</​o>​
 +<​r>"​Reached end of file."</​r>​
 +</​blockquote>​
 +
 +Normally one would not do this intentionally because it is not perspicuous,​ but beware when using '':​if-does-not-exist [[CL:​Constant Variables:​nil]]''​ that this doesn'​t happen to you accidentally...
 +
 +<​blockquote>​
 +(with-open-file (foo "​no-such-file"​ :​if-does-not-exist [[CL:​Constant Variables:​nil]])
 +  ([[CL:​Functions:​read]] foo))
 +<​o>​__hello?​__</​o>​
 +<​r>​HELLO?​ ; This value was read from the terminal, not a file!</​r>​
 +</​blockquote>​
 +
 +Here's another bug to avoid...
 +
 +<​blockquote>​
 +(with-open-file (foo "​no-such-file"​ :direction :​output ​
 +                                    :​if-does-not-exist [[CL:​Constant Variables:​nil]])
 +  ([[CL:​Functions:​format]] foo "​Hello"​))
 +<​r>"​Hello"​ ; FORMAT got an argument of [[CL:​Constant Variables:​NIL]]!</​r>​
 +</​blockquote>​
 +
 +====Side Effects====
 +Creates a //​[[CL:​Glossary:​stream]]//​ to the //​[[CL:​Glossary:​file]]//​ named by //​filename//​ (upon entry), and closes the //​[[CL:​Glossary:​stream]]//​ (upon exit). In some //​[[CL:​Glossary:​implementation|implementations]]//,​ the //​[[CL:​Glossary:​file]]//​ might be locked in some way while it is open. If the //​[[CL:​Glossary:​stream]]//​ is an //​[[CL:​Glossary:​output]]//​ //​[[CL:​Glossary:​stream]]//,​ a //​[[CL:​Glossary:​file]]//​ might be created.
 +
 +====Affected By====
 +The host computer'​s file system.
 +
 +====Exceptional Situations====
 +See the //​[[CL:​Glossary:​function]]//​ **[[CL:​Functions:​open]]**.
 +
 +====See Also====
 +  * **[[CL:​Functions:​open|Function OPEN]]**
 +  * **[[CL:​Functions:​close|Function CLOSE]]**
 +  * **[[CL:​Types:​pathname|System Class PATHNAME]]**
 +  * **[[CL:​Types:​logical-pathname|System Class LOGICAL-PATHNAME]]**
 +  * {\secref\PathnamesAsFilenames}
 +
 +====Notes====
 +None.
 +
 +\issue{DECLS-AND-DOC} \issue{STREAM-ACCESS:​ADD-TYPES-ACCESSORS} \issue{STREAM-ACCESS:​ADD-TYPES-ACCESSORS} \issue{WITH-OPEN-FILE-STREAM-EXTENT:​DYNAMIC-EXTENT} \issue{WITH-OPEN-FILE-DOES-NOT-EXIST:​STREAM-IS-NIL} \issue{WITH-OPEN-FILE-DOES-NOT-EXIST:​STREAM-IS-NIL} \issue{WITH-OPEN-FILE-SETQ:​EXPLICITLY-VAGUE} \issue{WITH-OPEN-FILE-DOES-NOT-EXIST:​STREAM-IS-NIL} \issue{FILE-OPEN-ERROR:​SIGNAL-FILE-ERROR} \issue{PATHNAME-LOGICAL:​ADD} \issue{FILE-OPEN-ERROR:​SIGNAL-FILE-ERROR} \issue{PATHNAME-HOST-PARSING:​RECOGNIZE-LOGICAL-HOST-NAMES}