From: Dennis Dunn
Subject: Random file access
Date: 
Message-ID: <ipgB6.524$rN4.376340@news3.mia>
Hello,

How do I position the file pointer to read the nth byte from a binary file
stream?  I could not find a function similar to the C librarys seek().

I would also like to know how to read a multibyte number from a binary
stream.  I have something that works but I assume it is the naive way to do
it.  Here is my code to read four bytes from the stream, I am reading the
header of an image.

(defun read-int (stream)
  "Read an int (4 bytes)  from the binary stream."
  (let ((ret 0))
    (setf ret (dpb (read-byte stream) (byte 8 0) ret))
    (setf ret (dpb (read-byte stream) (byte 8 8) ret))
    (setf ret (dpb (read-byte stream) (byte 8 16) ret))
    (setf ret (dpb (read-byte stream) (byte 8 24) ret))))

Is there a more platform independent way of doing this?

I have been reading "ASNI Common Lisp" by Graham and I am using the
LispWorks Personal Edition on Win98 to learn about Lisp programming.

Thanks.

--dennis
From: Frode Vatvedt Fjeld
Subject: Re: Random file access
Date: 
Message-ID: <2h7l0qb5vl.fsf@dslab7.cs.uit.no>
"Dennis Dunn" <········@bellsouth.net> writes:

> How do I position the file pointer to read the nth byte from a
> binary file stream?  I could not find a function similar to the C
> librarys seek().

Do have a look at FILE-POSITION.

> I would also like to know how to read a multibyte number from a
> binary stream.  I have something that works but I assume it is the
> naive way to do it.  Here is my code to read four bytes from the
> stream, I am reading the header of an image.

My binary-types package does exactly this and more. You'll find it at
<URL:http://www.cs.uit.no/~frodef/sw/binary-types/>

I've never used it with LispWorks though, so please let me know if you
have trouble getting it to work.

> (defun read-int (stream)
>   "Read an int (4 bytes)  from the binary stream."
>   (let ((ret 0))
>     (setf ret (dpb (read-byte stream) (byte 8 0) ret))
>     (setf ret (dpb (read-byte stream) (byte 8 8) ret))
>     (setf ret (dpb (read-byte stream) (byte 8 16) ret))
>     (setf ret (dpb (read-byte stream) (byte 8 24) ret))))

With binary-types, this can be done for example like this:

  (let ((*endian* :little-endian))
    (read-binary 'u4 stream))

> Is there a more platform independent way of doing this?

That depends what you mean by platform independent. You do need in one
way or another to specify the endianess and size of your
integers. Sometimes (but certainly not always) you want that
specification to be "the same as my C compiler". Your system's FFI
subsystem will typically provide an interface to "your C compiler",
but often only at a code/linkage level, not for streams. And the FFI
is of course also not "platform independent".

Binary-types is platform independent in the sense that if you for
example specify little-endian format as in my example above, a stream
containing little-endian integers will be read correctly regardless of
the native endianness of the machine you happen to be running on. The
same is true of your READ-INT function above, by the way.

-- 
Frode Vatvedt Fjeld