수색…


통사론

  • (read-char &optional stream eof-error-p eof-value recursive-p) => 문자
  • (write-char character &optional stream) => 문자
  • (read-line &optional stream eof-error-p eof-value recursive-p) => 라인, 누락 - 개행 -p
  • (write-line line &optional stream) => 라인

매개 변수

매개 변수 세부 묘사
stream 읽거나 쓸 스트림입니다.
eof-error-p 파일 끝에 도달하면 오류가 표시되어야합니다.
eof-value eof가 발생하고 eof-error-p 가 false이면 어떤 값을 반환해야합니다.
recursive-p READ 로부터 재귀 적으로 호출 된 READ 연산인가? 대개 NIL 로 남겨 두어야합니다.
character 쓸 문자 또는 읽은 문자.
line 쓰려는 줄 또는 읽은 줄.

문자열에서 입력 스트림 만들기

WITH-INPUT-FROM-STRING 매크로는 문자열에서 스트림을 만드는 데 사용할 수 있습니다.

(with-input-from-string (str "Foobar")
  (loop for i from 0
        for char = (read-char str nil nil)
        while char
        do (format t "~d: ~a~%" i char)))
; 0: F
; 1: o
; 2: o
; 3: b
; 4: a
; 5: r
;=> NIL

MAKE-STRING-INPUT-STREAM 사용하여 수동으로 수행 할 수도 있습니다.

(let ((str (make-string-input-stream "Foobar")))
  (loop for i from 0
        for char = (read-char str nil nil)
        while char
        do (format t "~d: ~a~%" i char)))

문자열에 결과 출력하기

WITH-OUTPUT-TO-STRING 매크로는 문자열 출력 스트림을 만들고 끝에 결과 문자열을 반환하는 데 사용할 수 있습니다.

(with-output-to-string (str)
  (write-line "Foobar!" str)
  (write-string "Barfoo!" str))
;=> "Foobar!
;   Barfoo!"

MAKE-STRING-OUTPUT-STREAMGET-OUTPUT-STREAM-STRING 사용하여 수동으로 수행 할 수도 있습니다.

(let ((str (make-string-output-stream)))
  (write-line "Foobar!" str)
  (write-string "Barfoo!" str)
  (get-output-stream-string str))

회색 시내

회색 스트림은 사용자 정의 스트림을 허용하는 비표준 확장입니다. 이 클래스는 사용자가 확장 할 수있는 클래스 및 메서드를 제공합니다. 구현 설명서에서 회색 스트림을 제공하는지 확인해야합니다.

간단한 예를 들어, 임의의 문자를 반환하는 문자 입력 스트림은 다음과 같이 구현할 수 있습니다.

(defclass random-character-input-stream (fundamental-character-input-stream)
  ((character-table
    :initarg :character-table
    :initform "abcdefghijklmnopqrstuvwxyz
" ; The newline is necessary.
    :accessor character-table))
  (:documentation "A stream of random characters."))

(defmethod stream-read-char ((stream random-character-input-stream))
  (let ((table (character-table stream)))
    (aref table (random (length table)))))

(let ((stream (make-instance 'random-character-input-stream)))
  (dotimes (i 5)
    (print (read-line stream))))
; "gyaexyfjsqdcpciaaftoytsygdeycrrzwivwcfb" 
; "gctnoxpajovjqjbkiqykdflbhfspmexjaaggonhydhayvknwpdydyiabithpt" 
; "nvfxwzczfalosaqw" 
; "sxeiejcovrtesbpmoppfvvjfvx" 
; "hjplqgstbodbalnmxhsvxdox" 
;=> NIL

파일 읽기

WITH-OPEN-FILE 매크로를 사용하여 스트림으로 읽기 위해 파일을 열 수 있습니다.

(with-open-file (file #P"test.file")
  (loop for i from 0
        for line = (read-line file nil nil)
        while line
        do (format t "~d: ~a~%" i line)))
; 0: Foobar
; 1: Barfoo
; 2: Quuxbar
; 3: Barquux
; 4: Quuxfoo
; 5: Fooquux
;=> T

OPENCLOSE 사용하여 수동으로 동일하게 수행 할 수 있습니다.

(let ((file (open #P"test.file"))
      (aborted t))
  (unwind-protect
       (progn
         (loop for i from 0
               for line = (read-line file nil nil)
               while line
               do (format t "~d: ~a~%" i line))
         (setf aborted nil))
    (close file :abort aborted)))

READ-LINE 은 각 줄마다 새 문자열을 만듭니다. 느려질 수 있습니다. 일부 구현은 행을 문자열 버퍼로 읽을 수있는 변형을 제공합니다. 예 : Allegro CL에 대한 READ-LINE-INTO .

파일에 쓰기

WITH-OPEN-FILE 매크로를 사용하여 스트림으로 쓰기위한 파일을 열 수 있습니다.

(with-open-file (file #P"test.file" :direction :output
                                    :if-exists :append
                                    :if-does-not-exist :create)
  (dolist (line '("Foobar" "Barfoo" "Quuxbar"
                  "Barquux" "Quuxfoo" "Fooquux"))
    (write-line line file)))

OPENCLOSE 하여 수동으로 동일하게 수행 할 수 있습니다.

(let ((file (open #P"test.file" :direction :output
                                :if-exists :append
                                :if-does-not-exist :create)))
  (dolist (line '("Foobar" "Barfoo" "Quuxbar"
                  "Barquux" "Quuxfoo" "Fooquux"))
    (write-line line file))
  (close file))

파일 복사 중

파일의 바이트 당 바이트 복사

다음 함수는 내용의 종류 (일부 인코딩 또는 이진 데이터에서 줄의 문자가 될 수 있음)를 무시하고 정확한 바이트 / 바이트 복사를 수행하여 파일을 다른 바이트로 복사합니다.

(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-byte read-char 를 처리하는 read-charwrite-char 대신 바이트에서 작동합니다. read-byte 스트림 또는 읽을 바이트 반환 NIL 파일의 끝을 두 번째 옵션 파라미터 인 경우 NIL (그렇지 않으면 에러 신호).

대량 복사

정확한 사본, 이전 사본보다 효율적입니다. 1 바이트가 아닌 매번 큰 덩어리의 데이터로 파일을 읽고 쓰면됩니다 :

(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 의해 반환 된 두 값, 즉 다음 줄의 문자를 포함하는 새로운 문자열과 그 줄이 파일의 마지막이고 마지막 줄 바꿈 문자를 포함하지 않으면 참인 부울 값을 사용합니다 (에스). 이 경우 write-stringwrite-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 기능에 의해 자동 관리되기 때문입니다.

문자열을 읽고 쓰는 전체 파일 읽기 및 쓰기

다음 함수는 전체 파일을 새로운 문자열로 읽어 들여 반환합니다.

(defun read-file (infile)
  (with-open-file (instream infile :direction :input :if-does-not-exist nil)
    (when instream 
      (let ((string (make-string (file-length instream))))
        (read-sequence string instream)
        string))))

파일이 없으면 결과는 NIL 입니다.

다음 함수는 문자열을 파일에 씁니다. 키워드 매개 변수는 파일이 이미있는 경우 수행 할 작업을 지정하는 데 사용됩니다 (기본적으로 오류가 발생하며 허용되는 값은 with-open-file 매크로의 값입니다).

(defun write-file (string outfile &key (action-if-exists :error))
   (check-type action-if-exists (member nil :error :new-version :rename :rename-and-delete 
                                        :overwrite :append :supersede))
   (with-open-file (outstream outfile :direction :output :if-exists action-if-exists)
     (write-sequence string outstream)))

이 경우 write-sequencewrite-string 으로 대체 될 수 있습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow