Регистрация | Войти
Lisp — программируемый язык программирования

Ввод/Вывод

Перенаправление стандартного вывода

Вы можете сделать это так:

(let ((*standard-output* <some form generating a stream>))
  ...
)

*standard-output* - динамическая переменная. То значение, которое она получит внутри окружения, создаваемого формой let, не повлияет на ее значение в глобальном окружении, и после выполнения формы let старое значение *standard-output* восстановится независимо от того, вышли ли мы из let нормально, через return-form, исключение или как-то еще. (Это, кстати, причина, по которой глобальные переменные в common lisp стабильнее, чем в других языках.)

Если вы хотите перенаправить вывод в файл, вы можете написать нечто вроде

(with-open-file (*standard-output* "somefile.dat" :direction :output
                                   :if-exists :supersede
)

  ...
)

with-open-file - это удобный макрос, подробно рассмотренный в главе Файлы и директории. В данном примере *standard-output* связывается с файлом somefile.dat, выполняется тело макроса, файл закрывается и значение *standard-output* восстанавливается.

Faithful (корректный, точный?) output with Character Streams

1)

Под точным выводом подразумевается, что символы с кодами от 0 до 255 будут выводится как есть. Это значит, что можно выполнить (PRINC (CODE-CHAR 0..255) s) в поток и ожидать вывода 8-битных байт, что не является очевидным во времена Unicode и 16- или 32-битных представлений символов. При этом не обязательно, чтобы символы ä, ß, или þ имели свои CHAR-CODE в диапазоне 0..255 - реализация может свободно использовать любой код. Тем не менее

Быстрый пакетный ввод/вывод

Если вам нужно скопировать сразу много данных, и как источник, так и получатель - потоки (или одного типа), то программа будет очень быстро работать с использованием функций read-sequence и write-sequence:

(let ((buf (make-array 4096 :element-type (stream-element-type input-stream))))
  (loop for pos = (read-sequence buf input-stream)
        while (plusp pos)
        do (write-sequence buf output-stream :end pos)
)
)

Например, ниже следующий код быстро отдает через веб-сервер hunchentoot очень большие файлы:

(with-open-file (input-stream "./out/log.txt" :element-type '(unsigned-byte 8))
  (let ((output-stream (hunchentoot:send-headers))
        (buf (make-array 4096 :element-type (stream-element-type input-stream)))
)

    (loop for pos = (read-sequence buf input-stream)
       while (plusp pos)
       do (write-sequence buf output-stream :end pos)
)
)
)

разумеется одать файл можно и более простым способом (hunchentoot:handle-static-file), но этот код может оказаться полезным, если необходимо отдавать много генерируемых на лету данных, (которые могут не поместиться в памяти)

1)Не смог придумать не-албанский перевод даже заголовка, поэтому оставил до момента просветления
@2009-2013 lisper.ru