LISP:如何从文件中读取内容并将其写入另一个文件?

时间:2013-04-03 19:48:10

标签: file io lisp

我想编写一个函数,其中包含两个文件的名称作为参数,并将内容从第一个文件复制到第二个文件。

到目前为止,我编写了一个从文件中读取的函数:

(defun readFile (name)
 (let ((in (open name)))
  (format t "~a~%" (read-line in))
   (close in)))

将字符串写入文件的函数:

(defun writeFile (name content)
(with-open-file (stream name
    :direction :output
    :if-exists :overwrite
    :if-does-not-exist :create)
(format stream content)))

按照Savantes的说明,我再次写了这个函数,这就是它的样子:

(defun read-write-to-file (input-file output-file)
(WITH-OPEN-FILE (output-stream output-file
         :direction :output
         :if-exists :new-version
         :if-does-not-exist :create)
  (WITH-OPEN-FILE (input-stream input-file
                 :direction :input)
        (FORMAT output-stream "~a" (READ input-stream nil 'eof))
)))

现在唯一的问题是它没有读取整个文件。

5 个答案:

答案 0 :(得分:4)

您找到了with-open-file。用它来输入和输出。请勿使用openclose

打开两个文件,然后将write打开到输出流中的read-line输出流。

顺便说一下,你的WRITEFILE显然无法编译。

另外,请使用正确的名称和缩进。

问题更新后

编辑:

Read-line读取一行。您可以使用write-line编写它,以便保留您的行结尾。您需要在循环中执行此操作才能复制更多行。

提示:你应该在代码中用小写字母写下你的名字。读者会自动升级它们。我选择在上面写WRITEFILE来展示你所选择的名字是如何在内部对待的。资本化无关紧要。 Ll是相同的。名称的一部分通常用Lisp代码中的连字符分隔。

答案 1 :(得分:4)

Common Lisp食谱实际上包含了对您问题的答案:

http://cl-cookbook.sourceforge.net/io.html

请参阅该页面底部的“批量I / O”部分。

通过微小的更正和修改,代码将如下所示:

(defun my-copy-file (from-file to-file)
  (with-open-file (input-stream from-file
                :direction :input
                :element-type '(unsigned-byte 8))
    (with-open-file (output-stream to-file
                   :direction :output
                   :if-exists :supersede
                   :if-does-not-exist :create
                   :element-type '(unsigned-byte 8))
      (let ((buf (make-array 4096 :element-type (stream-element-type input-stream))))
    (loop for pos = (read-sequence buf input-stream)
       while (plusp pos)
       do (write-sequence buf output-stream :end pos))))))

这应该能够处理文本文件和二进制文件。

答案 2 :(得分:3)

可能是一个更简洁的解决方案,至少与上述一样快,使用ASDF(以及Quicklisp)附带的优秀copy-stream-to-stream包中的UIOP

(require 'uiop)
(defun file-copy (source destination)
  (with-open-file (in source :direction :input)
    (with-open-file (out destination :direction :output)
      (uiop:copy-stream-to-stream in out))))

它应该尽可能快(如果不是更多),因为它使用WRITE-SEQUENCE作为默认值。请参阅第一个链接,了解copy-stream-to-stream的其他选项。

答案 3 :(得分:2)

此功能将内容从第一个文件复制到第二个文件:

(defun my-function (first second)
  (cl-fad:copy-file first second))

(当然,必须加载cl-fad包)

彼得

答案 4 :(得分:1)

首先:不要为此目的使用'READ',请使用'READ-LINE'。 'READ'执行读取宏,这会打开一个安全漏洞。相反,你需要使用'WRITE-LINE'。

当您使用'READ-LINE'时,您应该看到它确实如此:它只读取一行,并且当没有要读取的行时,返回符号'EOF'或(在您的情况下)符号'EOF'。它还会在下一个'EOL'之后推进你的读指针(或类似的东西,我不熟悉流的实现细节),所以当你在该流上执行下一个'READ-LINE'时,将读取下一行。您现在只需要重复读取和写入,直到遇到文件结束。