From ... Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!newsfeeds.belnet.be!news.belnet.be!news2.kpn.net!news.kpn.net!nslave.kpnqwest.net!nloc.kpnqwest.net!nmaster.kpnqwest.net!nreader2.kpnqwest.net.POSTED!not-for-mail Newsgroups: comp.lang.lisp Subject: Re: reading a file into a string References: Mail-Copies-To: never From: Erik Naggum Message-ID: <3221610744163603@naggum.net> Organization: Naggum Software, Oslo, Norway Lines: 58 User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.1 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Sat, 02 Feb 2002 03:52:26 GMT X-Complaints-To: newsmaster@KPNQwest.no X-Trace: nreader2.kpnqwest.net 1012621946 193.71.66.49 (Sat, 02 Feb 2002 04:52:26 MET) NNTP-Posting-Date: Sat, 02 Feb 2002 04:52:26 MET Xref: archiver1.google.com comp.lang.lisp:25661 * Dr. Edmund Weitz | I want to read a whole (text) file into a string. And I wonder what | would be the best way to do it. The function is named file-contents in Allegro CL and is based on an earlier version of mine, which goes like this: (defun file-contents (pathname &rest open-arguments) "Map the current contents of the file named by PATHNAME into a vector, which is returned. OPEN-ARGUMENTS is a list of arguments passed to OPEN; it should not include a :DIRECTION argument. An :ELEMENT-TYPE argument also specifies the type of the returned vector. Returns NIL if the file does not exist and :IF-DOES-NOT-EXIST is NIL." (with-open-stream (stream (apply #'open pathname :direction :input open-arguments)) (when stream (let ((buffer (make-array (file-length stream) :element-type (stream-element-type stream)))) (if (= (read-sequence buffer stream) (length buffer)) buffer (error 'file-error :format-control "Incomplete READ-SEQUENCE from ~S." :format-arguments (list (pathname stream)) :pathname (pathname stream))))))) (defun (setf file-contents) (vector pathname &rest open-arguments) "Make the contents of the file named by PATHNAME become that of VECTOR, which is returned. OPEN-ARGUMENTS is a list of arguments passed to OPEN; it should not include either a :DIRECTION or an :ELEMENT-TYPE argument. Does nothing and returns NIL if the file exists and :IF-EXISTS is NIL. :IF-EXISTS defaults to :SUPERSEDE." (with-open-stream (stream (apply #'open pathname :direction :output :element-type (array-element-type vector) (append open-arguments '(:if-exists :supersede)))) (when stream (write-sequence vector stream)))) Allegro CL has very strong support for various external-formats, so if you specify (or default to) characater as the element type, this may do some work between the read system call and read-sequence, so although it is very fast and efficient, it is hard to beat a byte-for-byte copy -- check which external-formats are available and apply If you want byte-for-byte copies, use (unsigned-byte 8) as the element-type. The portable way to convert between (unsigned-byte 8) and character is to use (map #'string #'code-char ), but you can usually find a way to hack the type system so such a byte vector turns into a string, but this is not portable, of course. Please remember that element-type and external-format are available keyword arguments to open. | 2. Is there an ANSI-compliant solution that is comparable in | performance? The above should be. Notice that file-length is a standard function, but it applies to a stream, not to pathnames. /// 2002-02-02 -- In a fight against something, the fight has value, victory has none. In a fight for something, the fight is a loss, victory merely relief.