如何在 Common Lisp 中创建双向二进制流?

Log*_*ins 5 lisp common-lisp

我阅读了如何在 Common Lisp 中创建二进制流(不是文件)?,它描述了如何创建二进制流而不是双向流。我尝试使用引用的库自己完成,但失败了。我的尝试看起来像:

(defun make-test-binary-stream ()
  (make-two-way-stream (flexi-streams:make-in-memory-input-stream 
                         (vector))
   (flexi-streams:make-in-memory-output-stream)))
Run Code Online (Sandbox Code Playgroud)

我像这样使用它:

(let ((str (make-test-binary-stream))) 
   (lisp-binary:write-float :double 123.45d0 :stream str) 
   (lisp-binary:read-binary-type 'double-float str))
Run Code Online (Sandbox Code Playgroud)

我期望的结果是123.45d0,但它返回0.0d0

我如何创建一个行为符合我预期的二进制流,允许我写入一个值然后读回相同的值?我想要这样一个流来测试将流作为输入和输出到流的编码和解码函数的正确性。

cor*_*ump 4

双向流S是一对(I,O),其中I是输入流, 是O输出流。两个流不一定相关,它只是意味着当您从 读取时S,您从 读取I,当您写入 时S,您写入到O

在这里,您尝试从空序列支持的内存流中读取数据。流只是给出序列中的项目,但是作为流;在这里,流立即到达文件末尾。

匿名缓冲区

不直接回答问题,但我有时会使用lisp-binary,我测试的方式如下:

(with-input-from-sequence 
    (in (with-output-to-sequence (out)
          (write-float :double 123.45d0 :stream out)))
  (read-binary-type 'double-float in))
Run Code Online (Sandbox Code Playgroud)

我们来分解一下:

(flex:with-output-to-sequence (out)
  (write-float :double 123.45d0 :stream out))
Run Code Online (Sandbox Code Playgroud)

上面的代码在本地绑定out到一个流,该流写入隐藏的内存序列,并最终返回该序列。整个表达式返回一个字节缓冲区:

#(205 204 204 204 204 220 94 64)
Run Code Online (Sandbox Code Playgroud)

该缓冲区用于with-input-from-sequence绑定in到从该序列读取数据的本地流。read-binary-type使用该输入流来解码该值。

临时文件

(defpackage :so (:use :cl :lisp-binary :flexi-streams :osicat))
(in-package :so)
Run Code Online (Sandbox Code Playgroud)

osicat系统有一个宏可以在输入和输出模式打开临时文件:

(with-temporary-file (io :element-type '(unsigned-byte 8))
  (write-float :double pi :stream io)
  (file-position io 0)
  (read-binary-type 'double-float io))
Run Code Online (Sandbox Code Playgroud)

内存循环缓冲区

我找不到内存中 I/O 流的现有实现,可以从/向同一向量读取和写入;你可以用两个共享内部向量的灵活流来破解某些东西(但这很危险,在某些情况下数据一致性会破坏),或者从灰色流构建一个;另请参见cl-stream