Re: force eof on an output stream



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.

(with-open-file (in #p"/path/to/bigfile" :direction :input)
(with-open-file (out #p"/path/to/bigfile"
:direction :output
:if-exists :overwrite)
(dotimes (i 300) (read-line in))
(handler-case
(loop (princ (read-line in) out) (terpri out))
(error ()))

would leave the last 300 lines duplicated at the end of the file... Is
it possible to "force" an eof to an output stream? I'm just a pig
farmer and don't know these kind of things...

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)))

Otherwise, you could try to use some implementation and OS specific
feature, like FFI to truncate(2) (which isn't even defined for normal
POSIX, you need the XSI extension).

--
__Pascal Bourguignon__ http://www.informatimago.com/
Kitty like plastic.
Confuses for litter box.
Don't leave tarp around.
.