鉴于我调用write
输出一些值(可能是原子,列表,点线对(,有没有办法找出写了多少个字符?是在调用之前还是之后,还是使用一些类似的功能?
如果你正在写信给file-stream
, 您可以使用file-position
write
之前和之后.
当流没有位置的概念(例如,broadcast-stream
(时,人们必须求助于。 到write-to-string
加write-string
:
(defun write-and-count (object &rest args &key stream &allow-other-keys)
"Write object to stream and return the number of characters written."
(let ((start (ignore-errors (file-position stream))))
(if start
(progn ; file stream
(apply #'write object args)
(- (file-position stream) start))
(progn ; something more complex
(remf args :stream)
(length (write-string (apply #'write-to-string object args) stream))))))
(with-open-file (s "foo" :direction :output)
(write-and-count '(1 2 3) :stream s))
==> 7
(write-and-count '(1 2 3) :stream *standard-input*)
(1 2 3) ; output
==> 7 ; return value
(write-and-count '(1 2 3))
(1 2 3) ; output
==> 7 ; return value
注释:
file-position
方法只是对大型物体的优化。- 需要
remf
以避免write-to-string
中的illegal keyword/value pair
错误。 - 流可能很棘手;不能保证
(write x :stream s)
等同于(write-string (write-to-string x) s)
。想想(广泛实现,但不是官方的(灰色流:如果你写到一个广播到普通file-stream
和漂亮打印的灰色流的broadcast-stream
,你将write
不同数量的字符到两个流。您希望返回的字符数是多少?第一计?第二?他们的总和?
更复杂的方法是使用灰色流,这是一种基于 CLOS 的 I/O 流变体,曾经由 David N. Gray 提出。许多实现以某种方式支持它。例如,可以编写新的流类并为输出函数编写:after
方法,这将记录写入字符的数量。
灰色流提供可扩展的基于 CLOS 的 I/O 流。
如果人们已经编写了这样的功能,我不会感到惊讶......
请参阅简单的灰色流,了解多个实现的兼容层。