Это дополнение к ответу coredump. В частности, я думаю, что поведение вашего кода правильное: SBCL делает правильные вещи в реализации потоков Грея, и он действительно должен сигнализировать об исключении здесь.
В вашем коде шаблон вызовов :
read-byte
(без дополнительных аргументов) для ваших binary-input-stream
вызовов stream-read-byte
в том же потоке; - ваш метод на
stream-read-byte
напрямую вызывает read-byte
в потоке, который вы завершили, не запрашивая ошибок и возвращая EOF :eof
, и возвращает значение этого вызова без дальнейшей проверки; - , который, в свою очередь, предположительно проходит через метод
stream-read-byte
завернутый поток, но нам не нужно об этом беспокоиться.
Итак, что это должно делать? Ну, я не уверен, где правильное место для окончательного документирования серых потоков, но здесь есть нечто, что может быть близко к нему .
В этом документе 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
- это специальное значение only , которое может возвращать stream-read-byte
.
Что ж, ваш метод на stream-read-byte
действительно возвращает :eof
, чтобы указать конец файла, тщательно исключено исключение, что внутренний вызов yo read-byte
мог бы сигнализировать иначе, так что это метод с хорошим поведением.
Но тогда external вызов 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
.