I am 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 plain text file.
I get the error
#<SB-SYS:FD-STREAM for "file /home/me/file.txt" {1004A90813}> is not
a character output stream.
Even using :element-type 'character
doesn't save me. I haven't been able to get any output stream opened by any method. If I try to use write-bit
it says that it isn't a binary output stream. No other write functions work either, such as write-sequence
or write-line
. They all return this error. How do I fix this?
I've made the important points bold. The problem is actually more tricky then one might think:
Let's look at the form.
First mistake: it's not indented correctly. Let's indent:
(with-open-file (output (open #p"file.txt"
:direction :output
:if-exists :overwrite))
(format output "test")))
Now we can see more mistakes. An additional parentheses
(with-open-file (output (open #p"file.txt"
:direction :output
:if-exists :overwrite))
(format output "test"))) ; <- additional parenthesis
But more important:
(open #p"file.txt"
:direction :output
:if-exists :overwrite)
Above opens a file for writing output and returns a stream.
WITH-OPEN-FILE
does also open a file. So you try to open the file TWICE, first for writing..
(with-open-file (output stream)
(format output "test")))
Above opens a file for reading. You have opened the file twice: first for writing, then for reading.
Now you try to write with FORMAT
to an input stream.
The slightly surprising part is this: both open
and with-open-file
can take a file stream as a file spec. If it gets a file stream as a file spec, then the associated pathname 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 is not that the stream is not a character stream. It's not an output stream. The stream actually is a character input stream! Thus calling FORMAT
using the stream won't work. Let's write an assert to verify 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 extra question: Why is the following form working?
(with-open-file (input (open #p"file.txt")) ...)
It just opens the file TWICE for reading.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With