2015-07-11 3 views
3

Я нахожусь на SBCL на debian.Общие потоки выходных файлов Lisp SBCL

По какой-то причине, если я использую это:

(with-open-file (output (open #p"file.txt" 
       :direction :output 
       :if-exists :overwrite)) 
    (format output "test"))) 

Где file.txt это обычный текстовый файл.

Я получаю ошибку

#<SB-SYS:FD-STREAM for "file /home/me/file.txt" {1004A90813}> is not 
a character output stream. 

Даже при использовании :element-type 'character не спасает меня. Я не смог получить какой-либо выходной поток, открытый каким-либо методом. Если я попытаюсь использовать write-bit, он говорит, что это не двоичный выходной поток. Никакие другие функции записи не работают, например write-sequence или write-line. Все они возвращают эту ошибку. Как это исправить?

ответ

9

Я сделал важные моменты жирным. Проблема на самом деле более сложная, чем можно подумать:

Давайте посмотрим на форму.

Первая ошибка: Правильно ли она не с отступом. Отступ:

(with-open-file (output (open #p"file.txt" 
           :direction :output 
           :if-exists :overwrite)) 
    (format output "test"))) 

Теперь мы можем видеть больше ошибок. Еще Скобки

(with-open-file (output (open #p"file.txt" 
           :direction :output 
           :if-exists :overwrite)) 
    (format output "test"))) ; <- additional parenthesis 

Но более важно:

(open #p"file.txt" 
     :direction :output 
     :if-exists :overwrite) 

Над открывает файл для записи выходных данных и возвращает поток.

WITH-OPEN-FILE также открывает файл. Так вы пытаетесь открыть файл ДВАЖДЫ, первый для написания ..

(with-open-file (output stream) 
    (format output "test"))) 

Над открывает файл для чтения. Вы открыли файл дважды: сначала для записи, затем для чтения.

Теперь вы пытаетесь написать FORMAT входному потоку.

Немного удивительное заключается в следующем: как open и with-open-file может взять файловый поток в качестве файла спецификации. Если он получает поток файлов как файл spec, то связанное с ним имя пути используется для операции open.

Итак, как уже упоминалось в другом ответе, это было бы более правильным:

(with-open-file (output #p"file.txt" 
         :direction :output 
         :if-exists :supersede) 
    (format output "Hello")) 

SBCL сообщение об ошибке:

#<SB-SYS:FD-STREAM for "file /home/me/file.txt" {1004A90813}> 
is not a character output stream. 

Точка сообщения об ошибке здесь не то, что поток не является символьным потоком. Это не выходной поток. Поток фактически является символом вход поток! При этом вызов FORMAT с использованием потока не будет работать. Напишем Assert проверить это:

CL-USER 18 > (with-open-file (output (open #p"/tmp/file.txt" 
              :direction :output 
              :if-does-not-exist :create 
              :if-exists :overwrite)) 
       (assert (output-stream-p output) (output) 
         "The stream ~a is not an output stream!" 
         output) 
       (format output "test")) 
Error: The stream #<STREAM::LATIN-1-FILE-STREAM /tmp/file.txt> 
is not an output stream! 

Ваш дополнительный вопрос: Почему следующий вид работает?

(with-open-file (input (open #p"file.txt")) ...) 

Он просто открывает файл TWICE для чтения.

+0

Благодарим вас за углубленный и информативный ответ. –

3

Неправильное использование вами with-open-file.

(with-open-file (output #p"file.txt" 
       :direction :output 
       :if-exists :supersede) 
    (format output "Hello")) 
+0

Это интересно, потому что '(with-open-file (input (open #p" file.txt "))' работал без проблем. –

Смежные вопросы