我想打开一个文件并读取内容,或者如果该文件不存在则执行其他操作.
前者可以很容易地完成:with-open-file.
对于后者,我的第一个想法是用来handler-case捕捉错误,但SBCL说它是SB-INT:SIMPLE-FILE-ERROR,这听起来像编译器内部符号,因此可能是不可移植的.
可移植的方法是什么?
使用:if-does-not-exist nil(见OPEN):
(defun test (path)
(with-open-file (stream path
:if-does-not-exist nil
:element-type '(unsigned-byte 8))
(if stream
(read-byte stream)
:something-else)))
Run Code Online (Sandbox Code Playgroud)
使用不存在的路径名:
(test #P"/hopefully/path/does/not/exist")
=> :SOMETHING-ELSE
Run Code Online (Sandbox Code Playgroud)
使用现有路径名:
(test #P"/dev/urandom")
=> 123
Run Code Online (Sandbox Code Playgroud)
您也可以使用PROBE-FILE来检查文件是否存在,如Rainer所解释的那样,但是在probe-file成功返回之后但在实际打开文件之前,您可能会被另一个进程删除该文件.
对于后者,我的第一个想法是使用handler-case来捕获错误,但是SBCL说它是SB-INT:SIMPLE-FILE-ERROR,它听起来像编译器内部符号,因此可能是不可移植的.
当您捕获特定于实现的错误时,您可以尝试检查其类层次结构以查找名称属于Common-Lisp包的最近的超类:
CL-USER> (inspect (find-class 'SB-INT:SIMPLE-FILE-ERROR))
The object is a STANDARD-OBJECT of type SB-PCL::CONDITION-CLASS.
0. %TYPE: (CLASS #<SB-PCL::CONDITION-CLASS SB-INT:SIMPLE-FILE-ERROR>)
...
5. DIRECT-SUPERCLASSES: (#<SB-PCL::CONDITION-CLASS COMMON-LISP:SIMPLE-CONDITION>
#<SB-PCL::CONDITION-CLASS COMMON-LISP:FILE-ERROR>)
6. DIRECT-SUBCLASSES: NIL
...
11. %CLASS-PRECEDENCE-LIST: (#<SB-PCL::CONDITION-CLASS SB-INT:SIMPLE-FILE-ERROR>
#<SB-PCL::CONDITION-CLASS COMMON-LISP:SIMPLE-CONDITION>
#<SB-PCL::CONDITION-CLASS COMMON-LISP:FILE-ERROR>
#<SB-PCL::CONDITION-CLASS COMMON-LISP:ERROR>
#<SB-PCL::CONDITION-CLASS COMMON-LISP:SERIOUS-CONDITION>
#<SB-PCL::CONDITION-CLASS COMMON-LISP:CONDITION>
#<SB-PCL::SLOT-CLASS SB-PCL::SLOT-OBJECT>
#<SB-PCL:SYSTEM-CLASS COMMON-LISP:T>)
...
Run Code Online (Sandbox Code Playgroud)
上面所说的是,在SBCL中,SB-INT:SIMPLE-FILE-ERROR有两个直接的超类,其中一个是COMMON-LISP:FILE-ERROR.
这是另一个使用CCL的例子:
? (handler-case (open #P"/tmp/foo/bar/baz/foo") (error (e) (inspect e)))
[0] #<CCL::SIMPLE-FILE-ERROR #x3020004DE7ED>
[1] Class: #<STANDARD-CLASS CCL::SIMPLE-FILE-ERROR>
[2] Wrapper: #<CCL::CLASS-WRAPPER CCL::SIMPLE-FILE-ERROR #x3020000F62DD>
Instance slots
[3] PATHNAME: #P"/tmp/foo/bar/baz/foo"
[4] CCL::ERROR-TYPE: "No such file or directory : ~s"
[5] CCL::FORMAT-CONTROL: #<Unbound>
[6] CCL::FORMAT-ARGUMENTS: (NIL)
Inspect> 1
[0] #<STANDARD-CLASS CCL::SIMPLE-FILE-ERROR>
[1] Class: #<STANDARD-CLASS STANDARD-CLASS>
...
[6] CCL::PRECEDENCE-LIST: (#<STANDARD-CLASS CCL::SIMPLE-FILE-ERROR>
#<STANDARD-CLASS SIMPLE-CONDITION>
#<STANDARD-CLASS FILE-ERROR> #<STANDARD-CLASS ERROR>
#<STANDARD-CLASS SERIOUS-CONDITION> ...)
...
[8] CCL::DIRECT-SUPERCLASSES: (#<STANDARD-CLASS SIMPLE-CONDITION>
#<STANDARD-CLASS FILE-ERROR>)
...
Run Code Online (Sandbox Code Playgroud)