鉴于我正在调用write
以输出某些值(可能是原子,列表,点对),有没有办法找出要写入多少个字符?是在通话之前还是之后,还是使用一些类似的功能?
答案 0 :(得分:4)
如果您正在写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
需要避免illegal keyword/value pair
中的write-to-string
错误。(write x :stream s)
等同于(write-string (write-to-string x) s)
。考虑一下(虽然不是正式的,但得到了广泛实施的)Gray streams:如果您写了一个broadcast-stream
,它会广播到一个普通的file-stream
和一个pretty-printing Gray stream,将{<3}}个不同个字符添加到两个流中。您希望返回的字符数是多少?第一算?第二?他们的总和?答案 1 :(得分:2)
更复杂的方法是使用灰色流,这是David N. Gray曾经提出的基于CLOS的I / O流变体。许多实现以某种方式支持它。例如,可以编写新的流类并为输出函数编写:after
方法,这些方法将记录所写字符的数量。
灰色流提供基于CLOS的可扩展I / O流。
如果人们已经编写了这样的功能,我不会感到惊讶...
有关几种实现的兼容性层,请参见trivial gray streams。