Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Newbie : file handling

Path: archiver1.google.com!news2.google.com!news.maxwell.syr.edu!newsfeed2.netcologne.de!news.netcologne.de!not-for-mail
From: Pascal Costanza <costa...@web.de>
Newsgroups: comp.lang.lisp
Subject: Re: Newbie : file handling
Date: Sat, 29 Nov 2003 16:22:16 +0100
Lines: 88
Distribution: world
Message-ID: <bqadjb$ooo$1@newsreader2.netcologne.de>
References: <bq9lq6$oag$1@news-reader1.wanadoo.fr>
NNTP-Posting-Host: xdsl-195-14-223-75.netcologne.de
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
X-Trace: newsreader2.netcologne.de 1070119339 25368 195.14.223.75 (29 Nov 2003 15:22:19 GMT)
X-Complaints-To: abuse@netcologne.de
NNTP-Posting-Date: Sat, 29 Nov 2003 15:22:19 +0000 (UTC)
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.5) Gecko/20031013 Thunderbird/0.3
X-Accept-Language: en-us, en
In-Reply-To: <bq9lq6$oag$1@news-reader1.wanadoo.fr>



Martin Raspaud wrote:
> Hi,
> 
> I'm just starting to write a lisp program for music and I want to open a 
> wav file and read its content and put it into an array.
> 
> Opening the file isn't much of a problem. The reading is more.
> The 4 first bytes of the file contain "RIFF"
> The next 4 bytes contain a 32bits integer giving the length of the file
> the next 4 bytes contain "WAVE"
> and so on.
> My question is : how do I get the length of the file with lisp ? I tried 
> "read-byte" with several type specifiers, but I can't get anything... 
> each time I get 4 numbers corresponding to the 4 bytes, but I want 1 
> number.
> 
> I hope anyone has an answer...

I have written the following code to read Java class files. They use 
8-bit bytes to encode 16-bit, 32-bit and 64-bit values in big endian 
order. I have taken the approach to load a complete class file at once 
into a byte array and then decode the values from that array. The idea 
was to wait for profiling the actual behavior in order to see whether a 
more efficient approach is needed. However, I haven't yet gotten to that 
stage.

Here is the code. Note that some Common Lisp implementations might have 
serious limitations on the possible maximum size of arrays.

(defmacro with-open-class-file ((cf pathname) &body block)
   "similar to with-open-file"
   (with-unique-names (result)
     `(let* ((,cf (open-class-file ,pathname))
             (,result (progn ,@block)))
        (setf ,cf ())
        ,result)))

(defun open-class-file (class-file)
   "similar to open-file"
   (with-open-file (stream class-file :element-type '(unsigned-byte 8))
     (let ((cf (make-array (file-length stream)
                           :element-type '(unsigned-byte 8)
                           :fill-pointer t)))
       (read-sequence cf stream)
       (setf (fill-pointer cf) 0)
       cf)))

(defun read1 (cf)
   "read one byte from a class file"
   (let ((fp (fill-pointer cf)))
     (incf (fill-pointer cf))
     (aref cf fp)))

(defun bytes-to-int (arr &key (start 0) (end nil) (signed nil))
   "take a multibyte datum in big-endian order"
   (when (null end) (setq end (length arr)))
   (assert (< start end))
   (let ((len (- end start))
         (res (reduce (lambda (x y) (logior (ash x 8) y)) arr
                      :start start :end end :initial-value 0)))
     (if (and signed (> len 0))
       (let ((dec (expt 2 (ash len 3))))
         (if (>= res (ash dec -1))
           (- res (expt 2 (* len 8)))
           res))
       res)))

(defun readn (cf n &key (signed nil))
   "read n bytes from a class file"
   (let* ((start (fill-pointer cf))
          (end (setf (fill-pointer cf) (+ start n))))
     (bytes-to-int cf :start start :end end :signed signed)))


The code uses only standard stuff per ANSI Common Lisp. I guess other 
people probably have suggestions for improvement. (This code is already 
derived from various hints I have gotten from past c.l.l postings.)


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."