重定向
(let ((*standard-output* <some form generating a stream>))...)
由于 *STANDARD-OUTPUT* 是个动态变量,所以执行是需要用 let 来绑定。在 LET 中,*STANDARD-OUTPUT* 之前的变量会保存下来,不论之前的值是什么。
如果要将一个程序的输出写入到一个文件中,可以使用如下格式:
(with-open-file (*standard-output* "somefile.dat" :direction :output:if-exists :supersede)...))
WITH-OPEN-FILE 将会打开一个文件(如果文件不存在就创建该文件),然后执行程序主体,将输出的结果写入到文件中,然后恢复原来 *STANDARD-OUTPUT*的值。
打印字符流
所谓的打印字符流就是将编码为0-255(8位,1字节)所表示的字符打印出来。
CLISP
:external-format(ext:make-encoding :charset 'charset:iso-8859-1 :line-terminator :unix)
同时也可以使用 (SETF (STREAM-ELEMENT-TYPE F) '(UNSIGNED-BYTE 8)),因为 SETF 是 CLISP 中额外的拓展。使用 :EXTERNAL-FORMAT :UNIX 时会存在移植性的问题,因为 MS-Windows 的默认编码是 CHARSET:CP1252,而 CHARSET:CP1252 不允许输出类似 (CODE-CHAR #x81) 这样的字符:
;*** - Character #\u0080 cannot be represented in the character set CHARSET:CP1252
ASCII 无法显示编码大于 127 的字符。
;*** - Character #\u0080 cannot be represented in the character setCHARSET:ASCII
CMUCL
:EXTERNAL-FORMATL :DEFAULT,没有测试过,无unicode,也没可以使用
AllegroCL
#+(AND ALLEGRO UNIX) :DEFAULT,也没测试过,Unix上应该可以使用,但是 MS-Windows 可能无法使用.
LispWorks
EXTERNAL-FORMAT '(:LATIN-1 :EOL-STYLE :LF),由 MArc Battyani 确认过。
例子:
(defvar *unicode-test-file* "faithtest-out.txt")(defun generate-256 (&key (filename *unicode-test-file*)#+CLISP (charset 'charset:iso-8859-1)external-format)(let ((e (or external-format#+CLISP (ext:make-encoding :charset charset :line-terminator :unix))))(describe e)(with-open-file (f filename :direction :output:external-format e)(write-sequence(loop with s = (make-string 256)for i from 0 to 255do (setf (char s i) (code-char i))finally (return s))f)(file-position f))));(generate-256 :external-format :default);#+CLISP (generate-256 :external-format :unix);#+CLISP (generate-256 :external-format 'charset:ascii);(generate-256)(defun check-256 (&optional (filename *unicode-test-file*))(with-open-file (f filename :direction :input:element-type '(unsigned-byte 8))(loop for i from 0for c = (read-byte f nil nil)while cunless (= c i)do (format t "~&Position ~D found ~D(#x~X)." i c c)when (and (= i 33) (= c 32))do (let ((c (read-byte f)))(format t "~&Resync back 1 byte ~D(#x~X) - cause CRLF?." c c) ))(file-length f)))#| CLISP(check-256 *unicode-test-file*)(progn (generate-256 :external-format :unix) (check-256)); uses UTF-8 -> 385 bytes(progn (generate-256 :charset 'charset:iso-8859-1) (check-256))(progn (generate-256 :external-format :default) (check-256)); uses UTF-8 + CRLF(on MS-Windows) -> 387 bytes(progn (generate-256 :external-format(ext:make-encoding :charset 'charset:iso-8859-1 :line-terminator :mac)) (check-256))(progn (generate-256 :external-format(ext:make-encoding :charset 'charset:iso-8859-1 :line-terminator :dos)) (check-256))| #
快速批量输入输出
当需要同时在源和目标流中拷贝大量的数据时,可以使用 READ-SEQUENCE 和 WRITE-SEQUENCE。
(let ((buf (make-array 4096 :element-type (stream-element-type input-stream))))(loop for pos = (read-sequence buf input-stream)while (plusp pos)do (write-sequence buf output-stream :end pos)))
