是否可以在 Scheme R6RS 中有效地从磁盘加载整个文件?
Is it possible to load an entire file from disk efficiently in Scheme R6RS?
以下 get_file
函数从磁盘读取文件作为 Scheme R6RS 字符串:
; Gets all characters from a port
(define (read_chars_from_port_rev port result)
(let ((char (read-char port)))
(if (eof-object? char)
result
(read_chars_from_port_rev port (cons char result)))))
; Gets the contents of a file as a string
; If it doesn't exist, returns empty
(define (get_file file)
(if (file-exists? file)
(let ((port (open-input-file file)))
(let ((text (list->string (reverse (read_chars_from_port_rev port '())))))
(begin
(close-input-port port)
text)))
""))
它的工作原理是打开文件,尾调用递归地将一个字符一个字符读入链表,直到找到eof,关闭文件,然后反转链表(因为尾调用)和将其转换为字符串。
这个过程应该比 Node.js 的 readFile
慢,因为它逐个读取一个字符,并为文件中的每个字符分配一个包含一个单元格的链表。理想情况下,我们应该能够将文件作为字符串缓冲区读取,而无需动态内存分配。
有什么方法可以使用 R6RS 中可用的原语来优化 get_file
吗?
您可以使用 get-string-all
:
> (let* ((fp (open-input-file "my-file.txt"))
(buf (get-string-all fp)))
(close-port fp)
(display buf))
Four score and seven years ago
our fathers brought forth upon this continent,....
会更方便
;;; Returns a string containing the contents of the file `fname`; closes the
;;; input port automatically (unless `get-string-all` does not return for
;;; some reason).
(define (get-file fname)
(call-with-input-file fname get-string-all))
> (get-file "my-file.txt")
"Four score and seven years ago\nour fathers brought forth upon this continent,....\n"
您可以使用 guard
来在查找的文件不存在时返回一个空字符串(如发布的代码中所示):
(define (guarded-get-file fname)
(guard (con
((i/o-file-does-not-exist-error? con) ""))
(call-with-input-file fname get-string-all)))
> (guarded-get-file "my-file.txt")
"Four score and seven years ago\nour fathers brought forth upon this continent,....\n"
> (guarded-get-file "oops.txt")
""
以下 get_file
函数从磁盘读取文件作为 Scheme R6RS 字符串:
; Gets all characters from a port
(define (read_chars_from_port_rev port result)
(let ((char (read-char port)))
(if (eof-object? char)
result
(read_chars_from_port_rev port (cons char result)))))
; Gets the contents of a file as a string
; If it doesn't exist, returns empty
(define (get_file file)
(if (file-exists? file)
(let ((port (open-input-file file)))
(let ((text (list->string (reverse (read_chars_from_port_rev port '())))))
(begin
(close-input-port port)
text)))
""))
它的工作原理是打开文件,尾调用递归地将一个字符一个字符读入链表,直到找到eof,关闭文件,然后反转链表(因为尾调用)和将其转换为字符串。
这个过程应该比 Node.js 的 readFile
慢,因为它逐个读取一个字符,并为文件中的每个字符分配一个包含一个单元格的链表。理想情况下,我们应该能够将文件作为字符串缓冲区读取,而无需动态内存分配。
有什么方法可以使用 R6RS 中可用的原语来优化 get_file
吗?
您可以使用 get-string-all
:
> (let* ((fp (open-input-file "my-file.txt"))
(buf (get-string-all fp)))
(close-port fp)
(display buf))
Four score and seven years ago
our fathers brought forth upon this continent,....
会更方便
;;; Returns a string containing the contents of the file `fname`; closes the
;;; input port automatically (unless `get-string-all` does not return for
;;; some reason).
(define (get-file fname)
(call-with-input-file fname get-string-all))
> (get-file "my-file.txt")
"Four score and seven years ago\nour fathers brought forth upon this continent,....\n"
您可以使用 guard
来在查找的文件不存在时返回一个空字符串(如发布的代码中所示):
(define (guarded-get-file fname)
(guard (con
((i/o-file-does-not-exist-error? con) ""))
(call-with-input-file fname get-string-all)))
> (guarded-get-file "my-file.txt")
"Four score and seven years ago\nour fathers brought forth upon this continent,....\n"
> (guarded-get-file "oops.txt")
""