因此,我专门研究了在 SBCL 上使用灰色流的 read-byte
方法。我遇到了一个奇怪的行为,其中 eof-error-p
参数似乎被忽略了。可能是我在我的代码中遗漏了一些微不足道的错误,但我已经看了十几遍了,但就是没看到。
假设有一个只有一个字节的文件test.txt
,比如说
echo -n 7 > test.txt
我希望下面的代码返回 :eof
(defclass binary-input-stream (fundamental-binary-input-stream)
((stream :initarg :stream :reader stream-of)))
(defmethod stream-read-byte ((stream binary-input-stream))
(format t "~a~%" "It's me, all right")
(read-byte (stream-of stream) nil :eof))
(defun make-binary-input-stream (stream)
(make-instance 'binary-input-stream :stream stream))
(with-open-file (in "test.txt" :element-type '(unsigned-byte 8))
(setq in (make-binary-input-stream in))
(read-byte in)
(read-byte in))
但是,SBCL 会抛出 END-OF-FILE
异常。这里发生了什么?
最佳答案
这是对 coredump 答案的补充。特别是我认为您的代码的行为是正确的:SBCL 在其灰色流的实现中做了正确的事情,它确实应该在这里发出异常信号。
在您的代码中,调用模式是:
read-byte
(没有可选参数)在您的binary-input-stream
调用同一流上的stream-read-byte
;- 你在
stream-read-byte
上的方法直接在你包装的流上调用read-byte
,要求没有错误并返回的 EOF :eof
,并返回该调用的值,无需进一步检查; - 这可能又会通过包装流的
stream-read-byte
方法,但我们不必为此担心。
那么,这应该做什么呢?好吧,我不确定 Gray 流的最终文档的正确位置在哪里,但是 here is something which may be close to it .
在该文档中,定义了stream-read-byte
:
STREAM-READ-BYTE stream [Generic Function]
Used by READ-BYTE; returns either an integer, or the symbol :EOF if the
stream is at end-of-file.
read-byte
定义为:
(defun READ-BYTE (binary-input-stream &optional (eof-errorp t) eof-value)
(check-for-eof (stream-read-byte binary-input-stream)
binary-input-stream eof-errorp eof-value))
最后 check-for-eof
定义为:
(defun check-for-eof (value stream eof-errorp eof-value)
(if (eq value :eof)
(report-eof stream eof-errorp eof-value)
value))
(我认为最后两个定义的真正意思是“实现需要做一些行为等同于此的事情”,特别是在流是灰色流的情况下需要这样做。)
因此 stream-read-byte
上的任何方法 不得 返回 :eof
除非流位于文件末尾,特别是这样做会导致发出异常信号(或者会导致 report-eof
被调用,无论如何,它可能会或可能不会发出异常信号)。 :eof
是stream-read-byte
可以返回的唯一 特殊值。
好吧,你在 stream-read-byte
上的方法确实返回 :eof
以指示文件结束,小心地抑制了内部调用 yo read-byte
否则会发出信号,因此这是一种行为良好的方法。
但随后对 read-byte
的外部 调用(如上定义)会看到此 EOF 值并尽职地为您引发异常。事实上,这正是您所要求的,因为您没有要求抑制这些调用中的异常。
如果您不想要异常,您需要确保对 read-byte
的外部调用要求异常不会发生,例如:
(with-open-file (in "test.txt" :element-type '(unsigned-byte 8))
(with-open-stream (bin (make-binary-input-stream in))
(values (read-byte bin nil ':eof)
(read-byte bin nil ':eof))))
对于单字节文件,这应该返回文件中的字节和 :eof
。
关于stream - 读取字节忽略 SBCL 灰色流中的 eof-error-p,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61107296/