复制文件

复制文件的每字节字节数

以下函数通过执行精确的每字节字节复制将文件复制到另一个文件中,忽略内容的类型(可以是某些编码中的字符行或二进制数据):

(defun byte-copy (infile outfile)
  (with-open-file (instream infile :direction :input :element-type '(unsigned-byte 8)
                            :if-does-not-exist nil)
    (when instream
      (with-open-file (outstream outfile :direction :output :element-type '(unsigned-byte 8)
                                 :if-exists :supersede)
        (loop for byte = (read-byte instream nil)
           while byte
           do (write-byte byte outstream))))))

(unsigned-byte 8) 类型是 8 位字节的类型。函数 read-bytewrite-byte 用于字节,而不是用于字符的 read-charwrite-charread-byte 返回从流中读取的字节,如果第二个可选参数是 NIL,则返回文件末尾的 NIL(否则表示错误)。

批量复制

精确的副本,比前一个更有效。可以通过每次读取和写入大块数据的文件来完成,而不是单个字节:

(defun bulk-copy (infile outfile)
  (with-open-file (instream infile :direction :input :element-type '(unsigned-byte 8)
                            :if-does-not-exist nil)
    (when instream
      (with-open-file (outstream outfile :direction :output :element-type '(unsigned-byte 8)
                                 :if-exists :supersede)
        (let ((buffer (make-array 8192 :element-type '(unsigned-byte 8))))
          (loop for bytes-read = (read-sequence buffer instream)
             while (plusp bytes-read)
             do (write-sequence buffer outstream :end bytes-read)))))))

read-sequencewrite-sequence 在这里使用缓冲区,缓冲区是字节向量(它们可以对字节或字符序列进行操作)。read-sequence 用每次读取的字节填充数组,并返回读取的字节数(当达到文件末尾时,可以小于数组的大小)。请注意,在每次迭代时都会破坏性地修改数组。

文件的每行精确复制行

最后一个示例是通过读取输入文件的每行字符并将其写入输出文件来执行的复制。请注意,由于我们需要精确的副本,因此我们必须检查输入文件的最后一行是否由行尾字符终止。出于这个原因,我们使用 read-line 返回的两个值:一个包含下一行字符的新字符串,以及一个布尔值,如果该行是文件的最后一行并且不包含最终换行符,则为 true (s )。在这种情况下,使用 write-string 代替 write-line,因为前者不会在行尾添加换行符。

(defun line-copy (infile outfile)
  (with-open-file (instream infile :direction :input :if-does-not-exist nil)
    (when instream
      (with-open-file (outstream outfile :direction :output :if-exists :supersede)
        (let (line missing-newline-p)
          (loop
             (multiple-value-setq (line missing-newline-p)
               (read-line instream nil nil))
             (cond (missing-newline-p                          ; we are at the end of file
                    (when line (write-string line outstream))  ; note `write-string`
                    (return))                                  ; exit from simple loop
                   (t (write-line line outstream)))))))))

请注意,此程序与平台无关,因为换行符(在不同的操作系统中有所不同)由 read-linewrite-line 函数自动管理。