2016-12-29 2 views
1

私はビットベクトルを持っています - #*10010010001001...Common Lispでビットベクトルからストリームを取得する方法は?

私はREAD-BYTEを使ってベクトルからオクテットを読みたいと思います。 しかし、バイナリストリームオブジェクトが必要です。

私はこれを行う方法を理解できないようです。私は(ビットベクトルから変換)、単純なベクトルから新たなストリームを取得するために、WRITE-SEQUENCEを使用してみました:

(WRITE-SEQUENCE (map 'array #'identity #*10010010...) *standard-output*) 

が、それはCHARACTERする必要が予想されるタイプについて不平を言います。

(私はClozure Common Lispのを使用しています。)

私が間違って何をしているのですか?

(答えとしてフレキシストリームを示唆しないでください。私はただ一つの小さなもののために全く新しいライブラリを追加する予定はありません。)

+1

あなたはビットのベクトルの代わりに、オクテットのベクトルを使用している理由はありますか? – jkiiski

+0

私は生のwebsocketフレームを作っています。個々のマスクビットなどを設定しなければならず、ベクトルとして表現(出力)される傾向のあるオクテットベクトルではなく、ビットベクトルとして視覚化して推論する方が簡単です。 REPLの整数の –

+0

@jkiiskiだから私はあなたのコメントから、八重奏ベクトルがストリームを取得して、それにread-byteを使うことがより簡単かもしれないと思った。私はビットベクトルをオクテットベクトルに変換することができましたが、それでもストリームを作成する方法はまだ分かりません... –

答えて

4

あなたは非標準のグレーストリーム拡張子を使用することができます独自のストリームクラスを定義します。オクテットベクトルのための簡単な例(私はSBCLを使用していますが、CCLはあまりにも灰色のストリームをサポートする必要があります):

(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 

ビットをマスクする必要についてコメントに関しては、bit-wise operatorsが標準です。オクテットベクトルの表示表現のために

(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 
> 
+0

!! Common Lisp(とあなた)は驚きと喜びを続けています!私はストリームがどのように作成されているかは完全にはわかりません。 stream-element-byteとstream-read-byteは何ですか?一般的な関数ですか?おそらく、グレーストリームが提供するものは?これについてちょっと説明できますか? –

+2

はい、汎用関数です。グレイストリームは基本的には、サブクラス化とジェネリック関数を持つことができるいくつかのクラス( 'fundamental-binary-input-stream'など)です。 [プロポーザル](http://www.nhplace.com/kent/CL/Issues/stream-definition-by-user.html)または[CCLマニュアルの関連する章](http:// ccl .clozure.com/manual/chapter10.2.html#独自のストリームクラスの作成とグレーストリーム) – jkiiski

+1

あなたの例はCCLで動作します。 –

関連する問題