scheme I/0 輸入輸出操做

2.1. open-input-fileread-char, and eof-object?

The function (open-input-file filename) is available to open a file. This function return a port for input. The function (read-char port) is to read a character from the port. As this function returns eof-object when it reaches the end of the file (EOF), you can check it by using eof-object?. The function (close-input-port port) is to close the input port. The [code 1] shows a function that returns file contents as string.html

[code 1]express

(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))))))
爲何要reverse,由於cons c ls1 是把先前讀取的放在後面,而c放在前面,爲何不(cons ls1 c)

#\!)
> (define c (cons 1 2))
> (cons c 3)
'((1 . 2) . 3)

> (cons 3 c)
'(3 1 . 2)app

把cons放在car位置上,會有一個(),而放在第二個則沒有函數

 

For instance, the result shown in [example 1] is obtained by applying the [code 1] to a file [hello.txt]. As the newline character is represented by '\n', it is not easy to read. Function display is available, however, for formatting ([example 2]).oop

[hello.txt]post

Hello world!
Scheme is an elegant programming language.

[example 1]ui

(cd "C:\\doc")
(read-file "hello.txt")
;Value 14: "Hello world!\nScheme is an elegant programming language.\n"

[example 2]this

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

2.2. Syntaxes call-with-input-file and with-input-from-file

You can open a file for input using the syntax call-with-input-file or with-input-from-file. These syntaxes are convenient because they handle errors.spa

( call-with-input-file  filename  procedure)
It opens a file named  filename for input. The  procedure is a function that takes input port as an argument. The file should be closed explicitly because it is not closed when the control is returned from the  procedure if the input port is potentially used again. The [code 1] can be rewritten like [code 2] using  call-with-input-file.

它打開一個文件來做爲輸入,接受一個函數(port作爲參數)設計

[code 2]

(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)))))))
( with-input-from-file  filename  procedure) 自動關閉
It opens a file named filename as the standard input. The  procedure is a function with no argument. The file is closed when the control is returned from the  procedure. [code 3] shows the rewritten function of [code 1] using  with-input-from-file.

[code 3]

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

2.3. read

The function (read port) reads a S-expression from the port. It is convenient to read contents with parentheses like [paren.txt]. (這個真是爲lisp專門設計的。

[paren.txt]

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

'(Lisp is a programming language ready to evolve.)

[code 4]

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

The following shows the result of reading paren.txt by s-read.

(s-read "paren.txt")
⇒ ((quote (hello world! scheme is an elegant programming language.))
(quote (lisp is a programming language ready to evolve.)))
demo1:

'(hello wrodl)
'(you )
'(can)

輸出:'('(hello wrodl) '(you) '(can))

demo2:

(you) (can)

'((you) (can))

demo3:
(you (we)) (can)
輸出:'((you (we)) (can))

Exercise 1

Write the function read-lines that returns a list of strings which correspond to each line of file contents. The newline character is represented by#\Linefeed in Scheme. Following is the result of applying this function to the hello.txt.

(read-lines "hello.txt") ⇒ ("Hello world!" "Scheme is an elegant programming language.")

3. Output to files

3.1. Making a Port for output

Similar functions to those for input are available to make output ports.

( open-output-file  filename)
It opens a file for output and returns a output port.
(close-output-port port)
It closes the port for output.
(call-with-output-file filename procedure)
It opens a file named  filename for output and calls  procedure. The function  procedure takes the port as an argument.
(with-output-to-file filename procedure)
It opens a file named  filename as the standard output and calls  procedure. The  procedure is a function with no argument. The file is closed when the control is returned from the  procedure.

3.1. Functions for output

Following functions for output are available. These functions output to the standard output if the port is omitted.

( write  obj  port)
It outputs the  obj to the  port. Strings are enclosed in double quotes and characters are combined with the  #\.
( display  obj  port)
It outputs the  obj to the  port. Strings are  not enclosed in double quotes and characters are  not combined with the  #\.
( newline  port)
It begins a new line.
( write-char  char  port)
It outputs the  char to the  port.
轉自: http://www.shido.info/lisp/scheme9_e.html

 

scheme 提供了一些輸入輸出過程,能夠調用它們讀取輸入端口,寫入輸出端口,而這些端口<port>能夠與控制檯<console>、文件<file>或者字符串<string>相關聯。
 
1.Reading<讀取>
 
scheme 讀取<reader>過程有一個可選輸入端口參數,默認是當前輸入端口<一般是控制檯>。
 
讀取能夠是基於字符、行或者是符號表達式。 在每一次讀取過程當中,端口的狀態都會更新,以使下一次讀取時從已經讀過的後面開始。若是一個端口已經讀取到結尾,讀取過程就返回 end-of-file 或 eof-object 對象,這個對象能夠用 eof-object? 函數來判斷
  • read-char 過程讀取指定端口下一個字符;
  • read-line 過程讀取指定端口的下一行,返回一個字符串<換行符會自動去掉>;
  • read 過程讀取指定端口的下一個符號表達式。
2.Writing<寫入>
 
scheme 寫入過程以一個被寫入對象和一個可選輸出端口爲參數,輸出端口默認是當前輸出端口<一般爲控制檯>。
  • write-char 過程把一個字符<不帶 #\>寫入到指定端口;
  • write 過程把一個符號表達式以一種 machine-readable 的形式寫入指定端口,好比,一個字符串會被雙引號括着,而字符會帶有 #\;
  • display 過程把一個符號表達式以一種 human-readable 的形式寫入指定端口,好比,一個字符串不會被雙引號括着,而一個字符不會帶有 #\。
3.File ports<文件端口>
 
scheme 輸入(輸出)過程以標準輸入(輸出)爲默認輸入(輸出)端口,因此當從標準輸入(輸出)讀取(寫入)時,不用指定端口,可是若是你想顯式的給出端口,能夠調用無參數的 current-input-port 和 current-out-port 過程:
?
1
2
3
scheme@(guile-user) > (display 9)
9scheme@(guile-user) > (display 9 (current-output-port))
9scheme@(guile-user) >
  • open-input-file 以一個文件名爲參數,返回與這個文件相關聯的輸入端口,當所給文件不存在時會報錯;
  • open-output-file 以一個文件名爲參數,返回與這個文件相關聯的輸出端口,當所給文件已存在時會報錯。
當對一個端口完成全部操做時,你應當用 close-input-port 和 close-output-port 來關閉它。
 
下面例子中,假設當前文件夾下 hello.txt 文件只含有 hello 一個詞:
scheme@(guile-user)> (define i (open-input-file "hello.txt"))
scheme@(guile-user)> (read-char i)
#\h
scheme@(guile-user)> (define j (read i))
scheme@(guile-user)> j
ello
scheme@(guile-user)> (read-char i)
#\newline
scheme@(guile-user)> (read-char i)
#<eof>
下面例子,假設當前文件夾下沒有 greeting.txt 文件:
 
1
2
3
4
5
6
scheme@(guile-user) > (define o (open-output-file "greeting.txt" ))
scheme@(guile-user) > (display "hello" o)
scheme@(guile-user) > (write-char #\space o)
scheme@(guile-user) > (display 'world o)
scheme@(guile-user) > (newline o)
scheme@(guile-user) > (close-output-port o)
此時,在當前文件夾下會有一個 greeting.txt 文件,文件內容爲:hello world
 
3.1 Automatic opening and closing of file ports<自動開關文件端口>
 
scheme 中的 call-with-input-file 和 call-with-output-file 過程會爲你自動打開一個端口,而且當你再也不用它時會自動關閉它。
 
call-with-input-file 過程以一個文件名和一個過程爲參數,而參數過程是以一個端口爲參數,而 call-with-input-file 過程的做用就是把與一個文件名相關的端口傳給其過程參數,而且當過程參數返回時確保該端口被關閉:
scheme@(guile-user) > (call-with-input-file "hello.txt"
...                     ( lambda (i)
...                        ( let * ((a (read-char i))
...                               (b (read-char i))
...                               (c (read-char i)))
...                           ( list a b c))))
(#\h #\e #\l)
call-with-output-file 過程與 call-with-input-file 過程類似,可是其所服務的對象是輸出文件。
 
4.String ports<字符串端口>
 
open-input-string 過程使一個字符串與一個端口相關聯,而那些讀取過程對該端口的操做就是讀出字符串中的內容:
scheme@(guile-user) > (define i (open-input-string "hello world" ))
scheme@(guile-user) > (read-char i)
#\h
scheme@(guile-user) > (read i)
ello
scheme@(guile-user) > (read i)
world
scheme@(guile-user) > (read i)
# < eof >
 
5.Loading file<加載文件>
 
load 過程會在當前模塊中順序執行當前文件夾下給定文件名中全部 scheme 語句

參考:
http://www.shido.info/lisp/scheme9_e.html

http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-9.html

http://lispor.is-programmer.com/posts/23271.html

相關文章
相關標籤/搜索