3

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

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

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

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

4

5 回答 5

5

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

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

于 2013-04-04T13:41:21.863 回答
4

你找到了with-open-file。将其用于输入和输出。不要使用openandclose来代替。

打开这两个文件,然后从输入流到write输出read-line流。

顺便说一句,您WRITEFILE显然无法编译。

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

问题更新后编辑:

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

提示:你应该在代码中用小写写你的名字。阅读器会自动将它们大写。我选择在WRITEFILE上面写,以显示您选择的名称在内部是如何处理的。大小写无关。 L并且l是相同的。在 Lisp 代码中,部分名称通常用连字符分隔。

于 2013-04-03T20:42:53.617 回答
3

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

(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

于 2015-07-22T18:21:33.577 回答
2

此函数将内容从第一个文件复制到第二个文件:

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

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

彼得

于 2015-08-21T12:28:32.350 回答
1

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

当您使用 'READ-LINE' 时,您应该会看到它确实做到了这一点:它只读取一行并返回该行,或者(在您的情况下)当没有行可读取时返回符号 'EOF'。它还会在下一个“EOL”之后推进您的读取指针(或类似的东西,我不太熟悉流的实现细节),因此当您在该流上执行下一个“READ-LINE”时,会读取下一行。您现在只需要反复读写,直到遇到文件末尾。

于 2013-04-04T12:48:16.910 回答