Re: force eof on an output stream



Pascal Bourguignon <pjb@xxxxxxxxxxxxxxxxx> wrote:
+---------------
| nallen05@xxxxxxxxx writes:
| > someone asked if it's possible to remove the first 300 lines of a file
| > without ever having two copies of the file or loading the entire thing
| > into memory.
....
| The best you can do, portably, is:
| (defun file-truncate-lines (file nlines)
| (let ((copy (merge-pathnames (make-pathname :type "TRU") file nil)))
| (with-open-file (in file)
| (with-open-file (out copy :direction :output
| :if-does-not-exist :create
| :if-exists :error)
| (loop :repeat nlines
| :for line = (read-line in nil nil)
| :while line
| :do (format out "~A~%" line))))
| (delete-file file)
| (rename-file copy file)))
+---------------

I think it was asking for "tail +300", not "head -300". That is,
the loop needs to look something like this:

(loop for i from 0
and line = (read-line in nil nil)
while line
when (>= i nlines)
do (format out "~a~%" line))

But READ-LINE conses, PEEK-CHAR & READ-CHAR not so much (at least,
not in implementations in which CHAR is an "immediate" type), so
when doing this sort of thing I tend to replace the ignored-value
READ-LINES as follows:

(loop repeat nlines
while (and (peek-char #\newline in nil nil)
(read-char in)))
(loop for line = (read-line in nil nil)
while line do
(format out "~a~%" line))

If NLINES is 29000 on a 30000-line file, the latter version will be
a *lot* faster... ;-}


-Rob

-----
Rob Warnock <rpw3@xxxxxxxx>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

.



Relevant Pages

  • Re: Beginner code - splitting lines on whitespace
    ... (defun scan-file () ... (loop for line = (read-line in nil nil) ...
    (comp.lang.lisp)
  • Re: Is it a bad sign...
    ... I just interned 11.6m symbols into package foobar: ... (loop for word = (read-line f nil nil) ... do (loop for i below 50 ... Timing the evaluation of (APROPOS:GIRAFFE:FOOBAR) ...
    (comp.lang.lisp)
  • Re: Strategies for defining named functions at load or compile time ?
    ... when (zerop n) return t ... try to compute a complicated unrolling of the loop each time. ... So the only thing that you need a macro for is to control the evaluation ... nil nil nil nil) ...
    (comp.lang.lisp)
  • Re: Read-from-string
    ... (loop repeat 3 collect (read s))) ... Is there a way to circumvent this "repeat ... (loop for token = (read s nil nil nil) ... (let ((data "lala tata bobo dada nil qwerty moo goo")) ...
    (comp.lang.lisp)
  • Re: Is a new CL standard possible?
    ... (loop for elt in list ... The functionality inside LOOP is eternally ...
    (comp.lang.lisp)