UP | HOME

输入/输出

Table of Contents

通过前面章节的学习,已经可以在 Scheme 的交互式前端中编写并执行程序了。在本章中,将介绍如何 输入输出

  使用输入输出,可以从文件中读取数据或向文件中写入数据

从文件输入

open-input-file,read-char 和 eof-object?

  • (open-input-file filename)打开 一个 文件
    • 返回一个 用于输入端口
  • (read-char port) :从 端口读取 一个 字符
    • 当读取到 文件结尾EOF )时,此函数返回 eof-object
  • eof-object? :检查是否已经到文件结尾
  • (close-input-port port)关闭 输入 端口

下面展示了以字符串形式返回了文件内容:

(define (read-file file-name)
  (let ((p (open-input-file file-name)))
    (let loop((ls1 '()) (c (read-char p)))
      (if (eof-object? c)
          (begin
            (close-input-port p)
            (list->string (reverse ls1)))
          (loop (cons c ls1) (read-char p))))))
hello.txt文件的内容如下:

  Hello world!
  Scheme is an elegant programming language.

测试读取 "hello.txt"文件:

(read-file "hello.txt")
;; "Hello world!\r\nScheme is an elegant programming language.\r\n"

发现 '\r\n' 这样的字符也被打印出来。也可使用 display 函数做 格式化输出

(display (read-file "hello.txt")) 
;;  Hello world!
;; Scheme is an elegant programming language.

call-with-input-file 和 with-input-from-file

   上面的代码并没有处理输入错误!!!

   下面的函数或语法打开文件的同时并处理错误

(call-with-input-file filename procedure)

  • 将名为 filename 的文件 打开 以供读取输入
  • 函数 procedure 接受一个 输入端口 作为参数
    • 文件有可能再次使用,因此当 procedure 结束时 文件不会自动关闭
    • 文件应该 显式地关闭
(define (read-file file-name)
  (call-with-input-file file-name
    (lambda (p)
      (let loop((ls1 '()) (c (read-char p)))
        (if (eof-object? c)
            (begin
              (close-input-port p)
              (list->string (reverse ls1)))
            (loop (cons c ls1) (read-char p)))))))

(display (read-file "hello.txt")) 
;;  Hello world!
;; Scheme is an elegant programming language.

(with-input-from-file filename procedure) :

  • 将名为 filename 的文件 打开 以供读取输入
  • 函数 procedure 没有任何参数
    • 当 procedure 结束时 文件自动关闭
(define (read-file file-name)
  (with-input-from-file file-name
    (lambda ()
      (let loop((ls1 '()) (c (read-char)))
        (if (eof-object? c)
            (list->string (reverse ls1))
            (loop (cons c ls1) (read-char)))))))

(display (read-file "hello.txt")) 
;;  Hello world!
;; Scheme is an elegant programming language.

read

(read port) : 从端口 port读入 一个 S-表达式

用它来读诸如“paren.txt”中带括号的内容就很方便

'(Hello world!
Scheme is an elegant programming language.)

'(Lisp is a programming language ready to evolve.)
(define (s-read file-name)
  (with-input-from-file file-name
    (lambda ()
      (let loop ((ls1 '()) (s (read)))
        (if (eof-object? s)
            (reverse ls1)
            (loop (cons s ls1) (read)))))))

(s-read "paren.txt")
; =>  ('(Hello world! Scheme is an elegant programming language.)
;;  '(Lisp is a programming language ready to evolve.))

输出到文件

打开一个用于输出的port

输出有和输入类似的函数,比如:

  • (open-output-file filename) : 打开 一个 文件 用作输出,返回该 输出端口
  • (close-output-port port) : 关闭 用于输出的 端口
  • (call-with-output-file filename procedure) :
    • 打开文件 filename 用于输出
    • 调用 过程 procedure
      • 该函数以 输出端口 为参数
      • 不会自动关闭 输出文件
  • (with-output-to-file filename procedure)
    • 打开文件 filename 作为 标准输出
    • 并调用过程 procedure
      • 该过程 没有参数
      • 过程 procedure 中返回时,文件被 自动关闭

输出的函数

下面的函数可用于输出。如果参数 port省略 的话,则输出至 标准输出

  • (write obj port) : 将 obj 输出至 port
    • 字符串双引号 括起
    • 字符 具有前缀 #\
  • (display obj port) : 将 obj 输出至 port
    • 字符串 双引号 括起
    • 字符 具有前缀 #\
  • (newline port) : 开始 新行
  • (write-char char port) :向 port 写入 一个 字符

Next:赋值

Previous:高阶函数

Home:目录