如何将文件内容读入Lisp中的列表?

Ste*_*ing 12 lisp file-io list common-lisp

我想将文件的内容读入列表.到目前为止,我的一些尝试是 -

(defun get-file (filename)
  (let ((x (open filename)))
    (when x
      (loop for line = (read-line x nil)
     while line do (list line)))
    (close x)))

(defun get-file (filename)
  (let ((x (open filename :if-does-not-exist nil)) (contents (list nil)))
    (when x
      (loop for line = (read-line x nil)
     while line do (cons contents line)))
    (close x) contents))

(defun get-file (filename)
  (let ((x (open filename :if-does-not-exist nil)) (contents nil))
    (when x
      (loop for line = (read-line x nil)
     while line do (append contents line)))
    (close x) contents))
Run Code Online (Sandbox Code Playgroud)

这些都没有奏效.谁能告诉我一个方法?或者甚至更好 - 如何将所有内容放入数组中?

Fra*_*rar 16

怎么样

(defun get-file (filename)
  (with-open-file (stream filename)
    (loop for line = (read-line stream nil)
          while line
          collect line)))
Run Code Online (Sandbox Code Playgroud)

  • `with-open-file`打开名为`filename`的文件,并将流与`f`相关联.`gather`在列表中收集`line`的各种值,直到`while`为`nil`.Common Lisp HyperSpec和Practical Common Lisp是你的朋友! (4认同)
  • 换句话说,`with-open-file`执行`open`和`close`以及`let`的所有工作. (3认同)

Rai*_*wig 11

问题在哪里?

(defun get-file (filename)
  (let ((x (open filename)))
    (when x
      (loop for line = (read-line x nil)
            while line
            do (list line)))    ; <-- you are not collecting, just doing
    (close x)))                 ; <- the function returns the value of CLOSE

(defun get-file (filename)
  (let ((x (open filename :if-does-not-exist nil))
        (contents (list nil)))
    (when x
      (loop for line = (read-line x nil)
            while line
            do (cons contents line)))  ; <-- again, the cons goes nowhere
    (close x) contents))               ; <-- CONTENTS has never been changed

(defun get-file (filename)
  (let ((x (open filename :if-does-not-exist nil))
        (contents nil))
    (when x
      (loop for line = (read-line x nil)
            while line
            do (append contents line)))  ; <- again the result goes nowhere
    (close x) contents))                 ; <-- CONTENTS has never been changed
Run Code Online (Sandbox Code Playgroud)

DO会执行一些副作用.

COLLECT将收集结果,然后LOOP将在退出时返回收集值的列表.

如前所述,使用WITH-OPEN-FILE而不是OPEN/CLOSE.WITH-OPEN-FILE将在离开动态范围时关闭文件.不仅从正常退出,而且在使用UNWIND-PROTECT的错误条件下.

如果要读取文件的内容,可以使用READ-SEQUENCE.与平常的问题.例如,当您将ASCII文件作为文本读入字符串时,该字符串可能比文件短.例如,Common Lisp将在CRLF为换行符的平台上用单个字符表示内部CRLF.另一个例子:在支持Unicode的实现中,文件中的UTF-8代码可能被替换为单个字符.


Ehv*_*nce 10

我将添加库.

编辑更简单,uiop包含在ASDF中:

(uiop:read-file-lines "file.txt")
Run Code Online (Sandbox Code Playgroud)

https://github.com/fare/asdf/blob/master/uiop/stream.lisp#L445

也有

(uiop:read-file-string "file")
Run Code Online (Sandbox Code Playgroud)

随着亚历山大read-file-into-string和分序列:

(alexandria:read-file-into-string "file.txt")
(split-sequence:split-sequence #\Newline *)
Run Code Online (Sandbox Code Playgroud)

str:

(str:lines (str:from-file "file.txt"))
Run Code Online (Sandbox Code Playgroud)

  • 这应该成为公认的答案。每次我需要加载文件时,我最终都会编写自己的实用程序函数。现在我知道我的编译器有两个(一个用于列表,一个用于单个字符串)。谢谢! (3认同)