LISP - 流
Lisp - I/O 流操作
Section titled “Lisp - I/O 流操作”Common Lisp 中的输入/输出(I/O)通过**流(streams)**处理。流是数据的源或汇,例如控制台、文件,甚至是字符串。这为与不同类型的数据源交互提供了统一的 API。
Common Lisp 提供了几个始终可用的标准流:
*standard-input*:默认输入流,通常连接到键盘。*standard-output*:默认输出流,通常连接到控制台显示器。*error-output*:用于打印错误消息和警告。*trace-output*:用于跟踪函数执行。
format 函数:您的输出首选
Section titled “format 函数:您的输出首选”尽管存在 write 和 write-line 等函数,但 format 函数是生成格式化输出最强大、最通用的工具。它的第一个参数是目标流(t 表示 *standard-output*),第二个参数是带有指令的控制字符串。
~a(美观 Aesthetic):以人类可读的方式打印对象。~s(S-表达式 S-expression):以机器可读的 Lisp 语法打印对象。~d(十进制 Decimal):以十进制打印整数。~%:打印换行符。~~:打印字面波浪号~。
(let ((name "World") (n 42)) (format t "Hello, ~a! The number is ~d.~%" name n)); Output: Hello, World! The number is 42.您还可以通过使用 nil 作为目标流来使用 format 创建字符串:
(let ((message (format nil "User ~a logged in." "Alice"))) (print message)); Output: "User Alice logged in."文件流:读写文件
Section titled “文件流:读写文件”文件 I/O 的最佳实践是使用 with-open-file 宏。它会自动打开文件,将流绑定到变量,最重要的是,即使发生错误,也能确保流在之后被关闭。
示例:文件写入与读取
Section titled “示例:文件写入与读取”(defun file-io-example () (let ((filename "greetings.txt")) ;; 写入文件 (with-open-file (out-stream filename :direction :output :if-exists :supersede) (format out-stream "Hello from Lisp!~%") (format out-stream "The year is ~d.~%" 2023))
(format t "File '~a' written successfully.~%~%" filename)
;; 从文件中读取并打印每一行 (format t "Reading from file:~%") (with-open-file (in-stream filename :direction :input) (loop for line = (read-line in-stream nil nil) while line do (format t " -> ~a~%" line)))))
;; 运行示例(file-io-example)您可以将文件操作包装在 handler-case 中,以优雅地处理潜在错误,例如文件未找到。
(handler-case (with-open-file (stream "non-existent-file.txt")) (file-error (c) (format *error-output* "Caught a file error: ~a~%" c)))字符串流允许您将字符串视为文件。这对于从字符串中解析数据或在内存中构建复杂字符串非常有用。
示例:从字符串流读取
Section titled “示例:从字符串流读取”(let ((data-string "user-id 12345")) (with-input-from-string (s data-string) (let ((header (read s)) (id (read s))) (format t "Header: ~s, ID: ~s~%" header id)))); Output: Header: USER-ID, ID: 12345高级主题:Gray Streams
Section titled “高级主题:Gray Streams”Gray Streams 是 Common Lisp 的一个标准化扩展,它允许您实现自己的自定义流类。这是一项高级功能,用于创建压缩数据、通过网络通信或与自定义硬件交互的流等任务。对于大多数应用程序而言,内置流类型已足够。