common-lisp
스트림
수색…
통사론
-
(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-STREAM
및 GET-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
OPEN
및 CLOSE
사용하여 수동으로 동일하게 수행 할 수 있습니다.
(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)))
OPEN
및 CLOSE
하여 수동으로 동일하게 수행 할 수 있습니다.
(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-byte
및 write-byte
함수 read-byte
read-char
를 처리하는 read-char
및 write-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-sequence
와 write-sequence
는 바이트의 벡터 인 버퍼에 사용됩니다 (바이트 또는 문자의 시퀀스에서 작동 할 수 있음). read-sequence
는 매번 읽은 바이트로 배열을 채우고 읽은 바이트 수를 반환합니다 (파일 끝에 도달하면 배열의 크기보다 작을 수 있음). 각 반복마다 배열이 파괴적으로 수정됩니다.
파일의 라인 당 정확히 복사
마지막 예는 입력 파일의 각 문자 행을 읽고 출력 파일에 기록하여 수행되는 사본입니다. 정확한 복사가 필요하기 때문에 입력 파일의 마지막 줄이 줄 끝 문자로 끝나는 지 확인해야합니다. 이러한 이유 때문에 우리는 read-line
의해 반환 된 두 값, 즉 다음 줄의 문자를 포함하는 새로운 문자열과 그 줄이 파일의 마지막이고 마지막 줄 바꿈 문자를 포함하지 않으면 참인 부울 값을 사용합니다 (에스). 이 경우 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-line
및 write-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-sequence
는 write-string
으로 대체 될 수 있습니다.