读写文件

; 读写文件
(open "/some/file/name.txt")
; 默认情况下open返回基于字符的流
READ-CHAR读取单个字符
READ-LINE读取一行自动去掉行结束符
READ读取一个S表达式,返回lisp对象
CLOSE关闭流
READ-BYTE读取二进制的一个字节(0-255的整数)
open参数:element-type '(unsigned-byte 8)
READ-SEQUENCE传递给他一个向量,一个流
他会尝试用来自流的数据填充该序列(向量),
返回序列中第一个没被填充的索引或者完全填充情况下序列的长度
可以指定:start :end 让其填充子序列
 
文件不存在默认报错
使用:if-does-not-exist 
:error ;默认值,报错
:create ;创建一个
nil ;返回nil代替流
(let ((in (open "/some/file.txt" 
                                :if-does-not-exist nil)))
    (when in
        (format t "~a~%" (read-line in))
        (close in)));打印文件第一行
读取时无意读到了末尾,默认报错
READ-CHAR READ-LINE READ接受一个可选参数
默认为真,在文件结尾处调用函数会报错
该参数是nil则遇到文件结尾处,
返回他们第三个参数的值,默认是nil
(defparameter *f* (open "c:/a.txt" 
                                                :if-does-not-exist :create))
(read-line *f* nil);nil
(read-line *f* nil "haha");"haha"
(loop for line = (read-line in nil)
    while line do (format t "~a~%" line))
; 写入文件
(open "/some/file/name.txt"
            :direction :output
            :if-exists (:append/:supersede/:overwrite/nil直接返回nil))
WRITE-CHAR写一个字符
WRITE-LINE写一行内容和一个换行
WIRTE-STRING写一个字符串
TERPRI无条件打印一个换行符
FRESH-LINE打印一个换行字符,除非该流已经到一行开始处
; lisp对象打印PRINT PPRINT PRIN1 PRINC
WRITE-BYTE二进制流写一个字节
WRITE-SEQUENCE批量输出
文件操作后忘记CLOSE流或者在CLOSE之前返回了
容易出现错误
为了确保一直运行特定代码的方案:
特殊操作符UNWIND-PROTECT
构建在之上的宏WITH-OPEN-FILE可以确保流自动关闭
(with-open-file (stream-var open-argument*)
    body-form*)
99%的情况下使用该宏,
例外情况是函数内打开文件,函数返回后继续使用流
 
路径名对象pathname
lisp认可的路径名描述符:
名字字符串,open返回的流,路径名对象
(pathname 路径名描述符) ;#p"c:/a/b/c.txt"
注意windows名字字符串中要用/或者\\
(pathname-directory 路径名描述符)
返回
(:absolute "a" "b")或者(:relative "a" "b")
pathname-name 文件名c
pathname-type 文件后缀名txt
pathname-host, pathname-device在windows下之一是盘符
pathname-version默认 :newest
路径名对象的读取语法 #p"路径字符串描述"
路径名对象到路径字符串描述的转化
(namestring #p"c:/a/b/c.txt");"c:/a/b/c.txt"
(directory-namestring #p"c:/a/b/c.txt");"/a/b/"
(file-namestring #p"c:/a/b/c.txt");"c.txt"
构造新的路径名MAKE-PATHNAME
(make-pathname 
    :directory '(:absolute "foo" "bar")
    :name "baz"
    :type "txt");#p"/foo/bar/baz.txt"
不推荐手工生成路径名对象,因为实现不同,不能跨平台
基于已有路径名来生成
带有html扩展名,其他组件都与变量input-file中的相同
(make-pathname :type "html"
                             :defaults input-file)
(make-pathname :type "html"
                             :defaults #p"c:/a/b/c.txt");#p"c:/a/b/c.html"
不同目录的情况
(make-pathname :directory '(:relative "backups")
                             :defaults #p"c:/a/b/c.txt");#p"c:backups/c.txt"
合并路径MERGE-PATHNAMES
至少一个带有相对目录组件
用第二个路径名的对应值填充第一个路径名中的任何nil组件
这和make-pathname使用:defaults参数的组件填充任何未指定组件一样
(merge-pathnames #p"b/c.txt" #p"c:/a");#p"c:/a/b/c.txt"
(pathname-directory #p"b/c.txt");(:relative "b")
(pathname-directory #p"/b/c.txt");(:absolute "b")
如果第二个路径名,目录组件是相对的则结果也是相对的
 
获取特定根目录下的文件名ENOUGH-NAMESTRING
(enough-namestring #p"/www/html/foo/bar.html" #p"/www/")
;"html/foo/bar.html"
(merge-pathnames
    (enough-namestring #p"/www/html/foo/bar.html" #p"/www/")
    #p"/www-backups/");#p"/www-backups/html/foo/bar.html"
系统自动合并路径merge-pathnames只有一个参数时
(make-pathname :name "foo" :type "txt")
(merge-pathnames (make-pathname :name "foo" :type "txt"))
发现win7结果是#P"c:/users/administrator/foo.txt"
实际上是和*default-pathname-defaults*组合的
 
目录名的两种表示方法,文件形式和目录形式
所以处理命名目录的路径名时,目录组件和名称组件分开
(make-pathname :directory '(:absolute "foo") :name "bar");#p"/foo/bar"文件形式
(make-pathname :directory '(:absolute "foo" "bar"));#p"/foo/bar/"目录形式
当前所有实现文件形式的,除非路径字符最后是路径分隔符结尾
(make-pathname :name "foo" 
                             :type "txt"
                             :defaults #p"/home/peter");#p"/home/foo.txt"
 
(make-pathname :name "foo" 
                             :type "txt"
                             :defaults #p"/home/peter/");#p"/home/pepter/foo.txt"
用户在输入上的一个错误,漏了一个/就导致了位置的错误
 
与文件系统交互
文件是否存在(probe-file #p"c:/a.txt")
probe-file,不存在返回nil存在返回文件名,
个别实现不支持
列举文件
(directory #p"C:/windows/")
;加上*.*返回列表
directory个别实现不支持
删除文件DELETE-FILE
delete-file 成功返回真否则FILE-ERROR
改名文件RENAME-FILE
(RENAME-FILE OLDNAME NEWNAME)
创建目录
(ENSURE-DIRECTORIES-EXIST #p"c:/aa");"c:/" T
(ENSURE-DIRECTORIES-EXIST #p"c:/aa/a.txt");"c:/aa/a.txt"实际上a.txt不会创建
容易内联使用
(with-open-file (out (ensure-directories-exist name))
                                         :direction :output
                                         ...写文件等...)
文件最后修改时间和文件作者
FILE-WRITE-DATE;从19000101后的秒数
FILE-AUTHOR
FILE-LENGTH;文件长度参数是流
(with-open-file (in filename :element-type '(unsigned-byte 8))
    (file-length in))
FILE-POSITION;参数是流,文件的当前位置已经读取或者写入元素的数量
设置流的位置
(FILE-POSITON 正整数)
(FILE-POSITON :start)
(FILE-POSITON :end)
 
其他IO类型
 
 
 
 
 
 
 
 
 
 
 
 
()




posted @ 2012-04-19 09:48  舜耕山翁  阅读(240)  评论(0编辑  收藏  举报