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 .



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow