common-lisp
Corrientes
Buscar..
Sintaxis
-
(read-char &optional stream eof-error-p eof-value recursive-p)
=> carácter -
(write-char character &optional stream)
=> carácter -
(read-line &optional stream eof-error-p eof-value recursive-p)
=> line, missing-newline-p -
(write-line line &optional stream)
=> línea
Parámetros
Parámetro | Detalle |
---|---|
stream | La secuencia para leer o escribir. |
eof-error-p | Si se señala un error si se encuentra el final del archivo. |
eof-value | Qué valor debe devolverse si se encuentra eof-error-p , y eof-error-p es falso. |
recursive-p | Es la operación de lectura llamada recursivamente desde READ . Por lo general, esto debe dejarse como NIL . |
character | El carácter a escribir, o el carácter que se leyó. |
line | La línea a escribir, o la línea que se leyó. |
Creando flujos de entrada desde cadenas
La macro WITH-INPUT-FROM-STRING
se puede utilizar para crear una secuencia a partir de una cadena.
(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
Lo mismo se puede hacer manualmente usando 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)))
Escritura de salida a una cadena
La macro WITH-OUTPUT-TO-STRING
se puede usar para crear una secuencia de salida de cadena y devolver la cadena resultante al final.
(with-output-to-string (str)
(write-line "Foobar!" str)
(write-string "Barfoo!" str))
;=> "Foobar!
; Barfoo!"
Lo mismo se puede hacer manualmente utilizando MAKE-STRING-OUTPUT-STREAM
y GET-OUTPUT-STREAM-STRING
.
(let ((str (make-string-output-stream)))
(write-line "Foobar!" str)
(write-string "Barfoo!" str)
(get-output-stream-string str))
Arroyos grises
Las transmisiones en gris son una extensión no estándar que permite transmisiones definidas por el usuario. Proporciona clases y métodos que el usuario puede ampliar. Debería consultar el manual de implementación para ver si proporciona flujos de Gray.
Para un ejemplo simple, una secuencia de entrada de caracteres que devuelve caracteres aleatorios podría implementarse así:
(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
Archivo de lectura
Se puede abrir un archivo para leerlo como un flujo usando la macro 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
Lo mismo se puede hacer manualmente usando OPEN
y 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)))
Tenga en cuenta que READ-LINE
crea una nueva cadena para cada línea. Esto puede ser lento. Algunas implementaciones proporcionan una variante, que puede leer una línea en un búfer de cadena. Ejemplo: READ-LINE-INTO
para Allegro CL.
Escribiendo en un archivo
Se puede abrir un archivo para escribirlo como una secuencia usando la macro 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)))
Lo mismo se puede hacer manualmente con OPEN
y 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))
Copiando un archivo
Copiar byte por byte de un archivo
La siguiente función copia un archivo en otro realizando una copia exacta de byte por byte, ignorando el tipo de contenido (que puede ser cualquiera de las líneas de caracteres en algunos datos de codificación o binarios):
(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))))))
El tipo (unsigned-byte 8)
es el tipo de bytes de 8 bits. Las funciones read-byte
y write-byte
funcionan en bytes, en lugar de read-char
y write-char
que funcionan en caracteres. read-byte
devuelve un byte leído desde el flujo, o NIL
al final del archivo si el segundo parámetro opcional es NIL
(de lo contrario, indica un error).
Copia masiva
Una copia exacta, más eficiente la anterior. Se puede hacer leyendo y escribiendo los archivos con grandes porciones de datos cada vez, en lugar de bytes individuales:
(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
se utilizan aquí con un búfer que es un vector de bytes (pueden operar en secuencias de bytes o caracteres). read-sequence
llena la matriz con los bytes leídos cada vez, y devuelve los números de bytes leídos (que puede ser menor que el tamaño de la matriz cuando se llega al final del archivo). Tenga en cuenta que la matriz se modifica destructivamente en cada iteración.
Copia exacta línea por línea de un archivo
El ejemplo final es una copia realizada leyendo cada línea de caracteres del archivo de entrada y escribiéndola en el archivo de salida. Tenga en cuenta que, dado que queremos una copia exacta, debemos verificar si la última línea del archivo de entrada está terminada o no por uno o más caracteres de final de línea. Por esta razón, usamos los dos valores devueltos por read-line
: una nueva cadena que contiene los caracteres de la siguiente línea y un valor booleano que es verdadero si la línea es la última del archivo y no contiene el carácter de nueva línea final (s). En este caso write-string
se utiliza write-string
lugar de write-line
, ya que el primero no agrega una nueva línea al final de la línea.
(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)))))))))
Tenga en cuenta que este programa es independiente de la plataforma, ya que los caracteres de nueva línea (que varían en diferentes sistemas operativos) se administran automáticamente mediante las funciones de write-line
read-line
write-line
.
Leyendo y escribiendo archivos enteros en y desde cadenas
La siguiente función lee un archivo completo en una nueva cadena y lo devuelve:
(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))))
El resultado es NIL
si el archivo no existe.
La siguiente función escribe una cadena en un archivo. Un parámetro de palabra clave se usa para especificar qué hacer si el archivo ya existe (de manera predeterminada causa un error, los valores admisibles son los de la macro 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)))
En este caso write-sequence
puede sustituirse write-string
.