stream - 读取字节忽略 SBCL 灰色流中的 eof-error-p

标签 stream lisp common-lisp sbcl

因此,我专门研究了在 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 被调用,无论如何,它可能会或可能不会发出异常信号)。 :eofstream-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/

相关文章:

iphone - 在单点触控中显示来自 Byte[] 的图像

node.js - 在转换流中实现背压

f# - 如何正确关闭流?

stream - 懒惰地串联一个可枚举的列表

common-lisp - sb-ext :run-program 的参数

emacs - 添加命令或环境到 AucTeX 自动完成列表

functional-programming - Racket 中的引用变量

lisp - 为什么需要在mapcar里面使用symbol-value来赋值?

common-lisp - Common Lisp 中的路径名,包含通配符的文件名

lisp - 使用带有 &key 参数的 remove-if-not