151 lines
5.2 KiB
Racket
151 lines
5.2 KiB
Racket
#lang scribble/doc
|
|
|
|
@(require (for-label scheme teachpack/2htdp/batch-io))
|
|
@(require scheme/sandbox scribble/manual scribble/eval scribble/core
|
|
scribble/html-properties scribble/latex-properties)
|
|
@(require "shared.ss")
|
|
|
|
@(require 2htdp/batch-io)
|
|
@(require scheme/runtime-path)
|
|
@(define-runtime-path here ".")
|
|
@(define io-style-extras
|
|
(list (make-css-addition (build-path here "io.css"))
|
|
(make-tex-addition (build-path here "io.tex"))))
|
|
@(define (file-is f)
|
|
(define x (parameterize ([current-directory here]) (read-file f)))
|
|
(centered
|
|
(tabular #:style (make-style "FileBox" io-style-extras)
|
|
(list (list (verbatim x))))))
|
|
|
|
@(define-syntax examples-batch-io
|
|
(syntax-rules ()
|
|
[(_ d ...)
|
|
(let ()
|
|
(define me (make-base-eval))
|
|
(begin
|
|
(interaction-eval #:eval me (require 2htdp/batch-io))
|
|
(interaction-eval #:eval me d)
|
|
...)
|
|
(me `(,current-directory ,here))
|
|
(interaction-eval #:eval me (require lang/htdp-intermediate-lambda))
|
|
me)]))
|
|
|
|
@; -----------------------------------------------------------------------------
|
|
|
|
@(define-syntax-rule (reading name ctc s)
|
|
@defproc[(@name [f (and/c string? file-exists?)]) @ctc ]{
|
|
reads the content of file @scheme[f] and produces it as @s .} )
|
|
|
|
@teachpack["batch-io"]{Batch Input/Output}
|
|
|
|
@author{Matthias Felleisen}
|
|
|
|
@defmodule[#:require-form beginner-require 2htdp/batch-io]
|
|
|
|
The batch-io teachpack introduces several functions and a form for reading
|
|
content from files and one function for writing to a file.
|
|
|
|
All functions that read a file consume the name of a file and possibly
|
|
additional arguments. They assume that the specified file exists in the
|
|
same folder as the program; if not they signal an error:
|
|
@itemlist[
|
|
|
|
@item{@reading[read-file string?]{a string, including newlines}
|
|
|
|
@examples[#:eval (examples-batch-io)
|
|
(read-file "data.txt")
|
|
]
|
|
assuming the file named @scheme["data.txt"] has this shape:
|
|
@(file-is "data.txt")
|
|
Note how the leading space in the second line translates into the space
|
|
between the newline indicator and the word @scheme["good"] in the result.}
|
|
|
|
@item{@reading[read-1strings (listof 1string?)]{a list of one-char strings, one per character}
|
|
|
|
@examples[#:eval (examples-batch-io)
|
|
(read-1strings "data.txt")
|
|
]
|
|
Note how this function reproduces all parts of the file faithfully,
|
|
including spaces and newlines.}
|
|
|
|
@item{@reading[read-lines (listof string?)]{a list of strings, one per line}
|
|
@examples[#:eval (examples-batch-io)
|
|
(read-lines "data.txt")
|
|
]
|
|
when @scheme["data.txt"] is the name of the same file as in the preceding
|
|
item. And again, the leading space of the second line shows up in the
|
|
second string in the list.}
|
|
|
|
@item{@reading[read-words (listof string?)]{a list of strings, one per white-space separated token in the file}
|
|
|
|
@examples[#:eval (examples-batch-io)
|
|
(read-words "data.txt")
|
|
]
|
|
This time, however, the extra leading space of the second line of
|
|
@scheme["data.txt"] has disappeared in the result. The space is considered
|
|
a part of the separator that surrounds the word @scheme["good"].
|
|
}
|
|
|
|
@item{@reading[read-words/line (listof string?)]{a list of lists, one per line; each line is represented as a list of white-space separated tokens}
|
|
|
|
@examples[#:eval (examples-batch-io)
|
|
(read-words/line "data.txt")
|
|
]
|
|
The results is similar to the one that @scheme[read-words] produces,
|
|
except that the organization of the file into lines is preserved.
|
|
In particular, the empty third line is represented as an empty list of words.
|
|
}
|
|
|
|
@item{@reading[read-csv-file (listof (listof any/c))]{a list of lists of comma-separated values}
|
|
|
|
@examples[#:eval (examples-batch-io)
|
|
(read-csv-file "data.csv")
|
|
]
|
|
where the file named @scheme["data.csv"] has this shape:
|
|
@(file-is "data.csv")
|
|
It is important to understand that the rows don't have to have the same
|
|
length. Here the third line of the file turns into a row of three
|
|
elements.
|
|
}
|
|
|
|
@item{@defproc[(@read-csv-file/rows [f (and/c string? exists?)][s
|
|
(-> (listof any/c) X?)]) (listof X?)]{reads the content of file @scheme[f] and
|
|
produces it as list of rows, each constructed via @scheme[s]}
|
|
|
|
@examples[#:eval (examples-batch-io)
|
|
(read-csv-file/rows "data.csv" (lambda (x) x))
|
|
(read-csv-file/rows "data.csv" length)
|
|
]
|
|
The first example shows how @scheme[read-csv-file] is just a short form
|
|
for @scheme[read-csv-file/rows]; the second one simply counts the
|
|
number of separated tokens and the result is just a list of numbers.
|
|
In many cases, the function argument is used to construct a structure from
|
|
a row.}
|
|
]
|
|
|
|
There is only one writer function at the moment:
|
|
@itemlist[
|
|
|
|
@item{@defproc[(write-file [f string?] [cntnt string?]) boolean?]{
|
|
turns @scheme[cntnt] into the content of file @scheme[f], located in the
|
|
same folder (directory) as the program. If the file exists when the
|
|
function is called, the function produces @scheme[true]; otherwise it
|
|
produces @scheme[false].}
|
|
|
|
@examples[#:eval (examples-batch-io)
|
|
(if (write-file "output.txt" "good bye")
|
|
(write-file "output.txt" "cruel world")
|
|
(write-file "output.txt" "cruel world"))
|
|
]
|
|
After evaluating this examples, the file named @scheme["output.txt"]
|
|
looks like this:
|
|
@(file-is "output.txt")
|
|
Explain why.
|
|
}
|
|
]
|
|
|
|
@(parameterize ([current-directory here])
|
|
(with-handlers ([exn:fail:filesystem? void])
|
|
(delete-file "output.txt")))
|
|
|