打印和报告输出的字符数



鉴于我调用write输出一些值(可能是原子,列表,点线对(,有没有办法找出写了多少个字符?是在调用之前还是之后,还是使用一些类似的功能?

如果你正在写信给file-stream, 您可以使用file-positionwrite之前和之后.

当流没有位置的概念(例如,broadcast-stream(时,人们必须求助于。 到write-to-stringwrite-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

注释

  1. file-position方法只是对大型物体的优化。
  2. 需要remf以避免write-to-string中的illegal keyword/value pair错误。
  3. 流可能很棘手;不能保证(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 流。

如果人们已经编写了这样的功能,我不会感到惊讶......

请参阅简单的灰色流,了解多个实现的兼容层。

最新更新