[Top][All Lists]
[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