Page 1 of 1

Binary I/O

Posted: Fri Jul 31, 2009 4:18 pm
by G4143
When you read this please understand that I'm very new to this great language.

I have a simple question about binary i/o. When I write to a file with element-type define as unsigned-byte 7(see code below) it produces a binary file that I can write and read back with no problems and that's great...I really like this feature. Now the question, when I enter the values 1,2,3,4,5,6,7,8.9,0 into the binary file – myfile it contains the values:

0A 00 00 00 01 C1 80 50 30 1C 10 09 00

Why does CLisp pad the first four bytes of this file with 0A 00 00 00 which is the number of entries...G4143

I found this at this web site- http://www.psg.com/~dlamkins/sl/chapter19.html

“the implementation is not required to directly map the specified :ELEMENT-TYPE onto the underlying file system; an implementation is permitted to alter the external format so long as data read from a binary file is the same as that written using the same :ELEMENT-TYPE”

Which is O.K. But why the padding of four bytes which seems to represent the number of entries? I'm just curious why this happens since it doesn't happen if the byte size is 8 or greater(at least I haven't experienced it with any other sizes)...G4143

Code: Select all

#! /usr/bin/clisp

(setq opstr (open "/home/share/test/myfile" :direction :output :element-type '(unsigned-byte 7)))

(let ((val 0))
  (loop
    (format t "~&~a" "enter a number, 0 to exit->")
    (setq val (read))
    (write-byte val opstr)
    (when (= val 0) (return 0)))
  )

(close opstr)

(setq opstr (open "/home/share/test/myfile" :direction :input :element-type '(unsigned-byte 7)))

(let ((val 0))
  (loop
    (setq val (read-byte opstr))
    (format t "~&val-> ~s~%" val)
    (when (= val 0) (return 0)))
  )

(close opstr)

Re: Binary I/O

Posted: Fri Jul 31, 2009 8:22 pm
by gugamilare
Since it is an unconventional element type for files, it looks like that Clisp puts a header in the file telling that it is not a conventional file. I tested it in SBCL and it seems that SBCL creates a file of (unsigned-byte 8) when you choose :element-type (unsigned-byte 7) or even :element-type (unsigned-byte 4). ECL does the same thing.

By the way, this is the code I used:

Code: Select all

(with-open-file (openstr "/tmp/myfile" :direction :output :element-type '(unsigned-byte 7)
                                  :if-exists :supersede)
           (write-sequence '(1 2 3 4 5 6 7 8 9 0) openstr))

(with-open-file (openstr "/tmp/myfile" :direction :input :element-type '(unsigned-byte 8))
           (loop for val = (read-byte openstr nil nil)
                while val collect val))
The behavior will change from implementation to implementation. If you need compatibility, use should use (unsigned-byte 8) files. You might want to take a look at the library odd-streams, which should portably provide the ability to create streams with other byte sizes (through implementations supporting gray-streams at least, but I believe that all or almost all implementation support gray-streams). Unfortunately, it has a few bugs, and even after correcting them it still didn't work here.

Re: Binary I/O

Posted: Mon Aug 03, 2009 7:56 pm
by G4143
Thank-you for the reply Gugamilare. I'm not sure what's harder, learning Common Lisp or rewriting the way I think about computer programming. Its probably the latter since I come from a background in C and have conditioned myself to think of problems as bits and bytes....Sometimes our knowledge is our greatest ignorance...G4143

Re: Binary I/O

Posted: Tue Aug 04, 2009 12:36 am
by skypher
It depends on the problem you're trying to solve. If you need to produce plain 7bit-files because some other (probably legacy) application requires that format then you should try to bend CL to do that (using ODD-STREAMS or some other means). Otherwise just use standard octets or no binary representation at all in favor of PRINT/READ.