guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: I/O, modules


From: Mark H Weaver
Subject: Re: I/O, modules
Date: Tue, 13 Nov 2012 09:31:05 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.2 (gnu/linux)

address@hidden writes:
> Could you show me some trivial programs related to I/O (e.g. read from
> file, convert to uppercase, write to another file)?

There are many ways to do this, but here's a simple upcase program that
reads the entire file into memory and does not depend on any external
modules:

--8<---------------cut here---------------start------------->8---
#!/usr/bin/guile \
-e main -s
!#

(use-modules (ice-9 match)
             (ice-9 rdelim))

(define (usage)
  (display "Usage: upcase <in-filename> <out-filename>\n")
  (exit 1))

(define (upcase-file in-filename out-filename)
  (call-with-input-file in-filename
    (lambda (in-port)
      (call-with-output-file out-filename
        (lambda (out-port)
          (display (string-upcase (read-delimited "" in-port))
                   out-port))))))

(define (main args)
  (setlocale LC_ALL "")
  (match args
    ((program in-filename out-filename)
     (upcase-file in-filename out-filename))
    (_ (usage))))
--8<---------------cut here---------------end--------------->8---

> This page [0] doesn't list a function that can be used to read the whole
> file at once.

As shown in the upcase program above, (read-delimited "" port) will read
the whole file as a string.  You need to (use-modules (ice-9 rdelim)) to
import this procedure.

Most of these procedures allow you to omit the 'port' argument, in which
case they will use (current-input-port) or (current-output-port).  Those
can be temporarily set within a block using 'with-input-from-file' and
'with-output-to-file'.  For example, 'upcase-file' above could be
written as follows:

   (define (upcase-file in-filename out-filename)
     (with-input-from-file in-filename
       (lambda ()
         (with-output-to-file out-filename
           (lambda ()
             (display (string-upcase (read-delimited ""))))))))

To read one line from a file, use (read-line port), which is also from
(ice-9 rdelim).  For example, we can use this to modify the upcase
program to read and write one line at a time, so that it will use less
memory for large files (as long as the lines aren't too long):

   (define (upcase-file in-filename out-filename)
     (call-with-input-file in-filename
       (lambda (in-port)
         (call-with-output-file out-filename
           (lambda (out-port)
             (define (loop)
               (let ((line (read-line in-port 'concat)))
                 (unless (eof-object? line)
                   (display (string-upcase line) out-port)
                   (loop))))
             (loop))))))

The 'concat argument to 'read-line' means that it should include the
end-of-line character(s), if any, in the returned string.  By default
they are stripped.

  Happy hacking!
      Mark



reply via email to

[Prev in Thread] Current Thread [Next in Thread]