Binary File IO Examples see also

;;; Creates a binary file with characters which couldn't be read

;;; or written by plain AutoLISP functions.

(defun testout (/ *error*)
  (defun *error* (s)
    (princ s)
    (binio-fcloseall))

  (binio-fcloseall)
  (if (and (setq fn "test.bin")
           (setq f (binio-fopen fn "w"))
      )
    (progn
      (binio-fputstring f "256 bytes 0 - 255:")

;; You may pass lists too which is faster

      (binio-fputc f (int-list 256))
      
      (binio-fputstring f "some doubles:")
      (setq i 0.0)
      (repeat 10
        (binio-fputstring f (std-rtos i))

;; Here we pass single reals

        (binio-fputreal f (setq i (+ i 0.1)))
      )

      (binio-fputstring f "10 longs:")

;; and here a list of 10 longs starting with 100,000

      (binio-fputlong f (inc-list 100000 10 '1+))

;; This appends a \0 at the end. Note the \r\n

;; instead of \n alone!

      (binio-fputs f "\r\nASCIIZ string")
      (binio-fclose f)
    )
    (std-error "Error creating file")
  )
)

;;; Reads that binary file back in. Also impossible in

;;; AutoLISP which cannot read 0x0

(defun testin (/ *error* i f failed)
  (defun *error* (s)
    (princ s)
    (binio-fcloseall))
  (defun compare (f read-func value / but)
    (if (= (setq but (apply read-func (list f))) value)
      (progn
        (princ "\nOK: ")
        (prin1 value))
      (progn
        (setq failed (1+ failed))
        (princ "\nFailed: ")
        (prin1 value) (princ " /= ")(prin1 but))))

  (setq failed 0)
  (binio-fcloseall)
  (if (and (setq fn "test.bin")
           (setq f (binio-fopen fn "r"))
      )
    (progn

;; Explicit compare

      (if (/= (binio-fgetstring f) "256 bytes 0 - 255:")
        (progn (setq failed (1+ failed)) 
               (princ "Failed: 1st fgetstring")))
      (setq i 0)
      (repeat 256

;; Now with our helper func which is shorter

        (compare f (function binio-fgetc) i)
        (setq i (1+ i)))

;; Note the \r\n instead of \n alone!

      (compare f (function binio-fgetstring) "some doubles:")
      (setq i 0.0)
      (repeat 10
        (compare f (function binio-fgetstring) (std-rtos i))
        (compare f (function binio-fgetreal) (setq i (+ i 0.1)))
      )

      (compare f (function binio-fgetstring) "10 longs:")
      (setq i (1- 100000))
      (repeat 10
        (compare f (function binio-fgetlong) (setq i (1+ i))))

;; This would fail with fputstring, that's why we used

;; puts instead.

;; Or we could use fgetstring (for \r\n the empty line)

;; and then fgets for the ASIIZ string

      (compare f (function binio-fgets) "\r\nASCIIZ string")
      (binio-fclose f)
      (princ "\ntest.bin successfully read\n")
    )
    (std-error "Error reading file")
  )
  (princ failed) (princ " tests of 280 failed\n")
  failed
)

;;; Some helpers:

;;; natural numbers until n: '(0 1 2 ... n)

;;; This is one way to define this. In the FAQ and in the

;;; stdlib there's an optimized version.

(defun int-list (n)
  (inc-list 0 n '1+))

;;; general incremented list: '(start 1+start ...)

;;; e.g.: (inc-list "A" 26 '(lambda (s) (chr (1+ (ascii (substr s 1 1))))))

(defun inc-list (start len incr-fun / lst)
  (setq lst (list start))
  (repeat (1- len)
    (setq lst (cons (setq start (apply incr-fun (list start)))
                    lst)))
  (reverse lst))