我想编写一个函数,其中包含两个文件的名称作为参数,并将内容从第一个文件复制到第二个文件。
到目前为止,我编写了一个从文件中读取的函数:
(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))
)))
现在唯一的问题是它没有读取整个文件。
答案 0 :(得分:4)
您找到了with-open-file
。用它来输入和输出。请勿使用open
和close
。
打开两个文件,然后将write
打开到输出流中的read-line
输出流。
顺便说一下,你的WRITEFILE
显然无法编译。
另外,请使用正确的名称和缩进。
问题更新后编辑:
Read-line
读取一行。您可以使用write-line
编写它,以便保留您的行结尾。您需要在循环中执行此操作才能复制更多行。
提示:你应该在代码中用小写字母写下你的名字。读者会自动升级它们。我选择在上面写WRITEFILE
来展示你所选择的名字是如何在内部对待的。资本化无关紧要。 L
和l
是相同的。名称的一部分通常用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'时,将读取下一行。您现在只需要重复读取和写入,直到遇到文件结束。