AfraLISP - Learn AutoLISP for AutoCAD productivity

File Handling

by Kenny Ramage

AutoLisp can only deal with one type of external file, namely an ASCII text file.
As well as this, AutoLisp can only read a file in sequential order. (It does not have random access.)
Despite these drawbacks, AutoLisp has certain basic tools that allow you to read and write one character at a time, or a full line at a time.
You can also append data to an existing file.

Working with external files is very simple.
First you "Open" the file.
Then you process the file by "Reading", "Writing" or "Appending" to it.
You then "Close" the file.
When you "Open" a file, Autolisp returns a file handle. This file handle is a name supplied by the operating system that let's you inform AutoLisp which file you want to work with.

Let's look at some examples.

(setq file (open "Testfile.txt" "w"))

AutoLisp should return something like this :

File: #28a27d2

This is the file handle returned by the operating system and stored in variable "file".
Try this now :

(write-line "This is some test data." file)

This "writes" a line of data to the file with handle "file".

(write-line "This is some more test data." file)

Let's write some characters to the same file :

(write-char 79 file)

This would write the ASCII character "O" to the file.

(write-char 75 file)

This would write the letter "K"
Now let's close the file :

(close file)

To read a file is just as simple :

(setq file (open "testfile.txt" "r"))

Open "Testfile.txt" to "Read".

(read-line file)

Read the first line.
Lisp should return :

"This is some test data "

Read the next line :

(read-line file)

Lisp should return :

"This is some more test data."

Let's read a character :

(read-char file)

Lisp will return :

79

It has returned the ASCII number.

(chr (read-char file))

Read the character AND convert it.
Lisp should return :

"K"
(read-line file)

Lisp should return "nil" as we have reached the end of the file.

Before moving on, you should always make sure that you close your files.

(close file)

Append is very similar to writing to a file except the file must already
exist if you want to append to it.

There are three other functions that write to an external file.
They are (princ), (prin1) and (print).
Let's have a look at them :

(setq file (open "afile.txt" "w"))
(princ "This is the (princ) function" file)
(prin1 "This is the (prin1) function" file)
(print "This is the (print) function" file)
(close file)

Open the file "afile.txt". You should have the following :

This is the (princ) function"This is the (prin1) function"
"This is the (print) function" 

All 3 functions display the result at the prompt line and send the
output to a file. Here are the differences :

(princ) displays strings without quotation marks.
(prin1) displays strings with quotation marks.
(print) displays strings with quotation marks and places a blank line
before the expression and a space afterwards.

Now we will look at a practical example :

The following is a Drawing Log Routine that logs the date, time, &
Drawing Name of each Drawing Session. It writes a report
to an ASCII Text file (Log.Txt).

(defun C:LOGIN ( / a c d file fp)
   (setq file (findfile "LOG.TXT"))
   (if (not file)
	(open "LOG.TXT" "w")
   );if
   (setq a (TODAY)
      TIME1 (TIME)
      c (getvar "DWGNAME")
      d (strcat "Drg Start   " a "  -  " TIME1 "  -  " c)
   );setq
   (if (/= c "Drawing.dwg")
      (progn  
         (setq file (findfile "LOG.TXT")
            fp (open file "a")
         );setq
         (princ d fp)
         (princ "\n" fp)
         (close fp)
         (princ (strcat "\nLogged in at : " TIME1))
      );progn
   );if
   (princ)
);defun
;;;*-------------------------------------------------
(defun C:LOGOUT ( / a c d file fp)
   (setq a (TODAY)
      TIME2 (TIME)
      c (getvar "DWGNAME")
      d (strcat "Drg Exit    " a "  -  " TIME2 "  -  " c)
   );setq
   (if (/= c "Drawing.dwg")
      (progn  
         (setq file (findfile "LOG.TXT")
            fp (open file "a")
         );setq
         (princ d fp)
         (princ "\n" fp)
         (close fp)
         (princ (strcat "\nLogged out at : " TIME2))
         (etime)
      );progn
   );if
   (princ)
);defun
;;;*-------------------------------------------------
(defun ETIME ( / hr1 m1 s1 tot1 hr2 m2 s2 tot2 total ht mt file fp)
   (setq hr1 (* 60 (* 60 (atof (substr time1 1 2))))
      m1 (* 60 (atof (substr time1 4 2)))
      s1 (atof (substr time1 7 2))
      tot1 (+ hr1 m1 s1)
      hr2 (* 3600 (atof (substr time2 1 2)))
      m2 (* 60 (atof (substr time2 4 2)))
      s2 (atof (substr time2 7 2))
      tot2 (+ hr2 m2 s2)
      total (- tot2 tot1)
      hr1 (/ total 3600)
      ht (fix hr1)
      hr1 (- hr1 ht)
      mt (* hr1 60)
      ht (rtos ht)
      mt (rtos mt) 
   );setq
   (setq d (strcat "Editing Time This Session :
  " ht " Hours and " mt " minutes"))
   (setq file (findfile "LOG.TXT")
      fp (open file "a")
   );setq
   (princ d fp)
   (princ "\n" fp)
   (princ "==========================
====================================" fp)
   (princ "\n" fp)
   (close fp)
   (princ)
);defun
;;;*-------------------------------------------
;;;*Calculates the Current Date
(defun TODAY ( / d yr mo day)
     (setq d (rtos (getvar "CDATE") 2 6)
          yr (substr d 3 2)
          mo (substr d 5 2)
         day (substr d 7 2)
     );setq
     (strcat day "/" mo "/" yr)
);defun
;;;*-------------------------------------------
;;;*Calculates the Current Time
(defun TIME ( / d hr m s)
     (setq d (rtos (getvar "CDATE") 2 6)
          hr (substr d 10 2)
           m (substr d 12 2)
           s (substr d 14 2)
     );setq
     (strcat hr ":" m ":" s)
);defun
(princ)

Load the file and type "Login" to run it. Leave it for a minute or so and then type "Logout" to exit the routine.
Have a look at the file Log.txt. It should look something like this :

Drg Start   07/12/98  -  15:36:31  -  F4443.dwg
Drg Exit    07/12/98  -  15:36:34  -  F4443.dwg
Editing Time This Session :  0 Hours and 0.05 minutes
==============================================================

Every time you log on and off the Starting Time, Ending Time and Total Editing Time will be appended to this file.

If you wish you can load Login.Lsp from your AcadDoc.Lsp file, and edit the Acad.mnu to call the Logout.Lsp routine before Exiting, Quiting or Starting a new drawing.

To download the source coding for this routine, just place you mouse
pointer here and click. (Gently please, I've got a hangover.)

For more information on this topic, refer to the External Data Tutorial.