Как создать двунаправленный двоичный поток в Common Lisp? - PullRequest
3 голосов
/ 02 июля 2019

Я прочитал Как создать двоичный поток (не файл) в 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)))

Я использую это как:

(let ((str (make-test-binary-stream))) 
   (lisp-binary:write-float :double 123.45d0 :stream str) 
   (lisp-binary:read-binary-type 'double-float str))

Результат, который я ожидаю, равен 123.45d0, но вместо этого он возвращает 0.0d0.

Как я могу создать двоичный поток, который ведет себя так, как я ожидал, позволяя мне записать значение в и затем прочитать то же значение обратно?Мне нужен такой поток для проверки правильности функций кодирования и декодирования, которые принимают потоки в качестве входных и выходных данных для потоков.

1 Ответ

2 голосов
/ 02 июля 2019

Двусторонний поток 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))

Давайте разложим:

(flex:with-output-to-sequence (out)
  (write-float :double 123.45d0 :stream out))

Вышеуказанное локально связывает out с потоком, который записывает в скрытую последовательность в памяти и в конечном итоге возвращает эту последовательность. Целое выражение возвращает буфер байтов:

#(205 204 204 204 204 220 94 64)

Этот буфер передается with-input-from-sequence для привязки in к локальному потоку, который читает данные из этой последовательности. read-binary-type использует этот входной поток для декодирования значения.

Временный файл

(defpackage :so (:use :cl :lisp-binary :flexi-streams :osicat))
(in-package :so)

В системе 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))

В памяти круговой буфер

Мне не удалось найти существующую реализацию потока ввода-вывода в памяти, который читает и записывает из / в один и тот же вектор; Вы можете взломать что-нибудь с помощью двух flexi-streams , которые имеют общий внутренний вектор (но это опасно, есть случаи, когда нарушается согласованность данных), или построили один из серых потоков; см. также cl-stream .

...