Vector 如何在Common Lisp中从位向量获取流?

Vector 如何在Common Lisp中从位向量获取流?,vector,common-lisp,Vector,Common Lisp,我有一个位向量-#*1001… 我想用READ-BYTE从向量中读出八位字节。 但它需要一个二进制流对象 我似乎不知道该怎么做。我尝试使用WRITE-SEQUENCE从一个简单向量(从位向量转换而来)获取一个新流: 但它抱怨期望的类型必须是字符 (我正在使用Clozure Common Lisp。) 我做错了什么 (请不要建议使用flexi streams作为答案。我不打算只为一件小事添加一个全新的库。)您可以使用非标准的Gray streams扩展来定义自己的流类。八进制向量的一个简单示例(我

我有一个位向量-
#*1001…

我想用READ-BYTE从向量中读出八位字节。 但它需要一个二进制流对象

我似乎不知道该怎么做。我尝试使用WRITE-SEQUENCE从一个简单向量(从位向量转换而来)获取一个新流:

但它抱怨期望的类型必须是字符

(我正在使用Clozure Common Lisp。)

我做错了什么


(请不要建议使用flexi streams作为答案。我不打算只为一件小事添加一个全新的库。)

您可以使用非标准的Gray streams扩展来定义自己的流类。八进制向量的一个简单示例(我使用SBCL,但CCL也应该支持灰色流):

对于八位向量的打印表示,您可以定义自己的pretty printer dispatch函数:

(defun print-octets (stream vector)
  (write-string "#<octet vector:" stream)
  (pprint-newline :mandatory stream)
  (loop for octet across vector
        do (format stream "~8,'0b " octet)
           (pprint-newline :fill stream))
  (pprint-newline :mandatory stream)
  (write-string ">" stream))


CL-USER> (set-pprint-dispatch '(vector (unsigned-byte 8)) #'print-octets)
CL-USER> (make-array 20 :element-type 'octet :initial-contents '(54 123 67 34 65 65 23 98 
                                                                 67 23 54 12 76 123 230 65 
                                                                 23 87 49 10))
#<octet vector:
00110110 01111011 01000011 00100010 01000001 01000001 00010111 01100010
01000011 00010111 00110110 00001100 01001100 01111011 11100110 01000001
00010111 01010111 00110001 00001010
>
(定义打印八位字节(流向量)

(write string“#使用位向量而不是八位向量有什么原因吗?我正在编写原始websocket帧,我必须设置单独的掩码位等等,而且更容易将其可视化和推理为位向量,而不是八位向量,这往往会被表示(输出)作为REPL中的整数向量。@jkiiski所以从你的评论中我认为使用八位向量可以更容易地获得流,这样我就可以在流上使用读取字节。我成功地将位向量转换为八位向量,但我仍然不太明白如何从它创建流…!!Common Lisp(还有你)继续惊喜吧!但是我不完全确定流是如何创建的。什么是流元素字节和流读取字节?通用函数?大概是灰色流提供了什么?你能详细说明一下吗?是的,它们是通用函数。灰色流基本上只是几个类(例如,
基本二进制输入流
),您可以对函数进行子类化和泛型化。您可以阅读或。
(deftype octet () '(unsigned-byte 8))

(defclass octet-input-stream (fundamental-binary-input-stream)
  ((data :initarg :data :type (vector octet))
   (position :initform 0)))

(defmethod stream-element-type ((stream octet-input-stream))
  'octet)

(defmethod stream-read-byte ((stream octet-input-stream))
  (with-slots (data position) stream
    (if (< position (length data))
        (prog1 (aref data position)
          (incf position))
        :eof)))

(let* ((arr (make-array 3 :element-type 'octet :initial-contents '(50 100 150)))
       (stream (make-instance 'octet-input-stream :data arr)))
  (loop for octet = (read-byte stream nil nil)
        while octet
        do (format t "~8,'0b~%" octet)))
; 00110010
; 01100100
; 10010110
(logior 50 #b00001000)
;=> 58
(defun print-octets (stream vector)
  (write-string "#<octet vector:" stream)
  (pprint-newline :mandatory stream)
  (loop for octet across vector
        do (format stream "~8,'0b " octet)
           (pprint-newline :fill stream))
  (pprint-newline :mandatory stream)
  (write-string ">" stream))


CL-USER> (set-pprint-dispatch '(vector (unsigned-byte 8)) #'print-octets)
CL-USER> (make-array 20 :element-type 'octet :initial-contents '(54 123 67 34 65 65 23 98 
                                                                 67 23 54 12 76 123 230 65 
                                                                 23 87 49 10))
#<octet vector:
00110110 01111011 01000011 00100010 01000001 01000001 00010111 01100010
01000011 00010111 00110110 00001100 01001100 01111011 11100110 01000001
00010111 01010111 00110001 00001010
>