From: David Bakhash
Subject: file to string conversion
Date: 
Message-ID: <cxjk8zjk9qk.fsf@engc.bu.edu>
hey,

If I wanted to simply read in a file as a string, what's the best way?

dave

From: Pierre Mai
Subject: Re: file to string conversion
Date: 
Message-ID: <87af0fzkx3.fsf@orion.dent.isdn.cs.tu-berlin.de>
David Bakhash <·····@bu.edu> writes:

> If I wanted to simply read in a file as a string, what's the best
> way?

READ-SEQUENCE is probably one of the best ways, if you want to stay
portable.  I.e. something along the following lines:

(defun get-file-as-string (filename)
  "Returns a string with the content of the file `filename'."
  (with-open-file (stream filename)
    (read-sequence (make-string (file-length stream)) stream)))

For production-quality code, you should check some of the semantics of
the interaction between ELEMENT-TYPE for OPEN/WITH-OPEN-FILE and
MAKE-STRING (I'm currently not sure, whether the standard guarantees
that ELEMENT-TYPE defaults to a type that's "compatible" with STRING.

You'd also probably not use MAKE-STRING, since MAKE-STRING initializes 
it's result, which causes unnecessary cache pollution...

Regs, Pierre

-- 
Pierre Mai <····@acm.org>               http://home.pages.de/~trillian/
  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]
From: Erik Naggum
Subject: Re: file to string conversion
Date: 
Message-ID: <3123377348984459@naggum.no>
* Pierre Mai <····@acm.org>
| READ-SEQUENCE is probably one of the best ways, if you want to stay
| portable.  I.e. something along the following lines:
| 
| (defun get-file-as-string (filename)
|   "Returns a string with the content of the file `filename'."
|   (with-open-file (stream filename)
|     (read-sequence (make-string (file-length stream)) stream)))
| 
| For production-quality code, you should check some of the semantics of
| the interaction between ELEMENT-TYPE for OPEN/WITH-OPEN-FILE and
| MAKE-STRING (I'm currently not sure, whether the standard guarantees
| that ELEMENT-TYPE defaults to a type that's "compatible" with STRING.

  you might also want to check out the return value from READ-SEQUENCE.

| You'd also probably not use MAKE-STRING, since MAKE-STRING initializes 
| it's result, which causes unnecessary cache pollution...

  well, it would if it did, but MAKE-STRING isn't required to initialize
  the allocated vector.  in particular, the `initial-element' argument's
  default value is implementation-dependent.  in Allegro CL 5.0, it is not
  initialized.  it can be quite an interesting read, actually.  (this
  taught me to zero out temporary strings used in functions with sensitive
  data -- I never thought I'd have to do _that_ in Common Lisp.)

  (I have written a SETF'able FILE-CONTENTS function that I use a lot, but
  my lawyer is working on the license stuff that should accompany all the
  code I want to publish.  all the licenses I have seen basically focus on
  making it easy to give something away, but very hard to accept it.  I
  want a license that makes it very easy to accept it in the simplest case
  (run it, use it, don't modify it, and don't re-distribute it, tell people
  where to find it), with options to get wider licenses (such as giving or
  licensing to me modifications of any kind, so the _single_ maintained
  version can be improved, and such that those who redistribute are
  required to accept all newer versions in addition to or replacing older
  versions, etc).  if anybody knows of a license that grants something like
  this (more details upon request), let me know -- it could save me a _lot_
  of lawyer fees.  both GNU GPL and LGPL are completely useless.  we're
  investigating the BSD license.)

#:Erik
-- 
  Nie wieder KrF!  Nie wieder KrF!  Nie wieder KrF!  Nie wieder KrF!
From: Pierre Mai
Subject: Re: file to string conversion
Date: 
Message-ID: <87g1a7rrv2.fsf@orion.dent.isdn.cs.tu-berlin.de>
Erik Naggum <····@naggum.no> writes:

>   you might also want to check out the return value from READ-SEQUENCE.

Oops, that comes from not posting the code you run through your
listener... Here a more correct version, just for those searching
through DejaNews:

(defun get-file-as-string (filename)
  "Returns a string with the content of the file `filename'."
  (with-open-file (stream filename)
    (let ((result (make-string (file-length stream))))
      (read-sequence result stream)
      result)))

> | You'd also probably not use MAKE-STRING, since MAKE-STRING initializes 
> | it's result, which causes unnecessary cache pollution...
> 
>   well, it would if it did, but MAKE-STRING isn't required to initialize
>   the allocated vector.  in particular, the `initial-element' argument's
>   default value is implementation-dependent.  in Allegro CL 5.0, it is not

My naive reading of MAKE-STRING, when narrowly interpreted, seems to
suggest otherwise:  Whereas initial-element's default value is
implementation dependent (i.e. can be anything), it still seems to
require that every element of the string returned is initialized to
this default value (whatever it is)...  

OTOH not initialising at all when no inital-element is supplied seems
to me to be the more useful option, but if this was intended, then it
should probably be more clearly stated in the standard...

Well, whatever, it's Christmas, have a nice time, I'll be back next
year ;)

Regs, Pierre.

-- 
Pierre Mai <····@acm.org>               http://home.pages.de/~trillian/
  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]
From: SLong
Subject: Re: file to string conversion
Date: 
Message-ID: <36A7DEE0.199E@isomedia.com>
David Bakhash wrote:
> 
> hey,
> 
> If I wanted to simply read in a file as a string, what's the best way?
> 
> dave

This defun (or something close to it) will allow you to a file
as a set of newline-delimited strings until it reaches End-Of-File.
When the keyword :return-as-string? allows the lines to be concatenated
into a single string; otherwise a list of the line-strings are
returned.

I did this off the top of my head based on what I remember doing in
an ICAD app weeks ago; it is intended to illustrate con-
cepts more than anything else. Can't guarantee this works. I will try
it in Common Lisp tomorrow and repost as required.

(defun retrieve-file-contents 
    (pathstring &key (return-as-string? nil))
  (labels ((readf (stream line-list)
              (let ((result (read-line stream nil 'done)))
                (if (not (eql result 'done))
                    (readf stream (push result line-list)
                  line-list
                 )
                )
              )
            (app-str (string list-of-strings)
              (if list-of-strings
                  (app-str 
                    (concatenate 
                     'string 
                     string 
                     (car list-of-strings)
                     #\newline
                     )
                    (cdr list-of-strings)
                    )
                   string
                 )
                )
             )
    (with-open-file (stream-in pathstring :direction :input)
      (let ((list-of-strings (reverse (readf stream-in nil))))
        (if return-as-string 
            (app-str "" list-of-strings)
          list-of-strings
          )
        )
     )
    )
 )