Common Lisp Streams of SBCL Output Files

I'm on SBCL on debian.

For some reason, if I use this:

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

      

Where file.txt

is a simple text file.

I am getting the error

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

      

Even using it :element-type 'character

doesn't save me. I was unable to get any output stream opened by any method. If I try to use write-bit

it says it is not a binary output stream. No other recording functions work, such as write-sequence

or write-line

. They all return this error. How to fix it?

+3


source to share


2 answers


I made the big moments bold. The problem is actually more complex than one might think:

Let's look at the shape.

First mistake: it is not indented correctly . Let's indent:

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

      

We can now see more errors. Additional parentheses

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

      

But more importantly:

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

      

The above opens a file to write the output and returns a stream.

WITH-OPEN-FILE

also opens the file. So you are trying to open a TWICE file, first for writing ..

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

      

Above, the file opens for reading. You have opened the file twice: first for writing, then for reading.



You are now trying to write from FORMAT

to the input stream.

The slightly surprising part is this: both open

and WITH-OPEN-FILE

can accept a file stream as a file spec. If it receives a file stream as a file specification, then the associated path is used for the open operation.

So, as mentioned in another answer, this would be more correct:

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

      

SBCL error message :

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

      

The point of the error message here does not mean that the stream is not a character stream. This is not an output stream. The stream is actually a stream of input . Thus, calling FORMAT

using a thread will not work. Let's have a statement written to test this:

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!

      

Your additional question : Why does the following form work?

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

      

It just opens the TWICE file for reading.

+9


source


Improper use with-open-file

.



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

      

+3


source







All Articles