Juan Reynoso Elias
En 2016-03-29 10:42:15


Streams
 

All of the I/O functions in lisp accept a stream argument. In some cases (e.g. READ and PRINT) the stream argument is optional; by default, input comes from the *STANDARD-INPUT* stream (normally connected to keyboard) and output goes to the *STANDARD-OUTPUT* stream (normally connected to display).

The power of streams comes from the ability to associate a stream with a file, a device (such as keyboard, display, or network), or a memory buffer. Program I/O can be directed at will by simply creating the appropriate type of stream for your program to use. The I/O implementation is abstracted away by the stream so your program won't have to be concerned with low-level details.


Creating streams on files

The OPEN function creates a FILE-STREAM. Keyword arguments determine attributes of the stream (:DIRECTION, :ELEMENT-TYPE, and :EXTERNAL-FORMAT) and how to handle exceptional conditions (:IF-EXISTS and :IF-DOES-NOT-EXIST). If OPEN is successful it returns a stream, otherwise it returns NIL or signals an error.

Keyword      Value     Stream Direction
----------   -------   -----------------------------
:DIRECTION   :INPUT    input (default)
:DIRECTION   :OUTPUT   output
:DIRECTION   :IO       input & output
:DIRECTION   :PROBE    none, returns a closed stream

Keyword      Value                Action if File Exists
----------   ------------------   ---------------------------------------
:IF-EXISTS   NIL                  return NIL
:IF-EXISTS   :ERROR               signal an error
:IF-EXISTS   :NEW-VERSION         next version (or error)
:IF-EXISTS   :RENAME              rename existing, create new
:IF-EXISTS   :SUPERSEDE           replace file upon CLOSE
:IF-EXISTS   :RENAME-AND-DELETE   rename and delete existing, create new
:IF-EXISTS   :OVERWRITE           reuse existing file (position at start)
:IF-EXISTS   :APPEND              reuse existing file (position at end)

Keyword              Value     Action if File Does Not Exist
------------------   -------   -----------------------------
:IF-DOES-NOT-EXIST   NIL       return NIL
:IF-DOES-NOT-EXIST   :ERROR    signal an error
:IF-DOES-NOT-EXIST   :CREATE   create the file

Keyword         Value               Element Type
-------------   --------------      ------------------------
:ELEMENT-TYPE   :DEFAULT            character (default)
:ELEMENT-TYPE   'CHARACTER          character
:ELEMENT-TYPE   'SIGNED-BYTE        signed byte
:ELEMENT-TYPE   'UNSIGNED-BYTE      unsigned byte
:ELEMENT-TYPE   character subtype   character subtype
:ELEMENT-TYPE   integer subtype     integer subtype
:ELEMENT-TYPE   other               implementation-dependent

Keyword            Value      File Format
----------------   --------   ------------------------
:EXTERNAL-FORMAT   :DEFAULT   default (default)
:EXTERNAL-FORMAT   other      implementation-dependent

Once you've opened a stream, you can use it with appropriate input or output functions, or with queries that return attributes of either the stream or the file. The following queries can be applied to all kinds of streams. All of these accept a stream argument:

Function               Returns
--------------------   -----------------------------------------------------
INPUT-STREAM-P         true if stream can provide input
OUTPUT-STREAM-P        true if stream can accept output
OPEN-STREAM-P          true if stream is open
STREAM-ELEMENT-TYPE    the type specifier for stream elements
INTERACTIVE-STREAM-P   true if stream is interactive (e.g. keyboard/display)

These queries can be applied to file streams. These also accept a stream argument:

Function                 Returns
--------------------     -----------------------------------------------------
STREAM-EXTERNAL-FORMAT   implementation-dependent
FILE-POSITION            current file offset for read or write, or NIL
FILE-LENGTH              length of stream, or NIL

FILE-POSITION returns a byte offset within the stream. This is an exact count for streams of integer subtypes (see below for further description of binary I/O). For streams of character subtypes, the position is guaranteed only to increase during reading or writing; this allows for variations in text record formats and line terminators.

FILE-POSITION can also be called with a second argument to change the file offset for the next read or write. When used for this purpose, FILE-POSITION returns true when it succeeds.

You should always close a stream when you're done using it (except for the interactive streams provided for you use by Lisp, such as *STANDARD-INPUT*, *STANDARD-OUTPUT*, and *TERMINAL-IO*). The "open, process, close" pattern is very common, so Lisp provides macros to make the pattern both easy to code and error-free.

WITH-OPEN-FILE is tailored for file streams. Its arguments are a variable to be bound to the stream, a pathname, and (optionally) keyword arguments suitable for OPEN. The stream is always closed when control leaves the WITH-OPEN-FILE form.

(with-open-file (stream "my-file.dat" :direction :input)
  ... do something using stream ...)

WITH-OPEN-STREAM expects a variable name and a form to be evaluated; the form should produce a stream value or NIL. This macro is commonly used with constructors for specialty streams, such as MAKE-BROADCAST-STREAM, MAKE-ECHO-STREAM, MAKE-TWO-WAY-STREAM, MAKE-CONCATENATED-STREAM, and MAKE-SYNONYM-STREAM.
 

Finally we have an example ready to run

(defun copy-a-file ()
  "Read a file and copy to"
  (let ((value-from-read-byte nil)
    (origin-path "/tmp/my-file.jpg")
    (new-path "/tmp/my-new-file.jpg"))
    (with-open-file (origin-file origin-path :direction :input :element-type 'unsigned-byte)
      (with-open-file (new-file new-path :direction :output :element-type 'unsigned-byte :if-exists :supersede)
    ;;Here we read the origin file and writing into the new file
    (loop
       ;; exit when get :eof (end of file)
       (when (equal value-from-read-byte :eof) (return nil))
       ;; reading the data
       (setf value-from-read-byte (read-byte  origin-file nil :eof))
       ;; writing the data; in other words copy a file
       (unless (equal value-from-read-byte :eof)
         (write-byte value-from-read-byte new-file)))))))


#lisp #streams

También te podría interesar