複製檔案

複製檔案的每位元組位元組數

以下函式通過執行精確的每位元組位元組複製將檔案複製到另一個檔案中,忽略內容的型別(可以是某些編碼中的字元行或二進位制資料):

(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 函式自動管理。