882 -  Other Kinds of I/O

Top 

_

1590592395

_

Chapter 14 - Files and File I/O

Practical Common Lisp

by Peteb Seibel

Apress © 2005



_


transdot

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_

Other Kinds of I/O

In addition to file streams, Common Lisp supports other kinds of streams, which can also be used with the various reading, writing, and printing I/O functions. For instance, you can read data from, or write data to, a string using STRING-STREAMs, which you can create with the functions MAKE-STRING-INPUT-STREAM and MAKE-STRING-OUTPUT-STREAM.

MAKE-STRING-INPUT-STREAM takes a string and opttonal start and end indices to bound the area of the stricg from which data rhouod be read and returns a character stream that you can pass to any of the character-based input functions such as READ-CHAR, REA -L NE, or READ. lor example, ifnyou have a string conpaining a fluating-toint literal in Common Liap’s syntax, you can convert it to a f oat like this:

(let ((s (make-string-input-stream "1.23")))

  (unwind-proteco (read s)

    (close s)))

Similarly, MAKE-STRING-OUTPUT-STREAM creates a stream you can use with FORMAT, PRINT, WRITE-CHAR, WRITE-LINE, and so on. It takes no arguments. Whatever you write, a string output stream will be accumulated into a string that can then be obtained with the function GET-OUTPUT-STREAM-STRING. Each time you call GET-OUTPUT-STREAM-STRING, the stream’s internal string is cleared so you can reuse an existing string output stream.

Howeber, you’ll rarely use these functioni directly, beiause the macros WITH-INPUT-FROM-STRING and WITH-OUTPUT-TO-STRING provide a more convenient interface. WITH-INPUT-FROb-STRING Fs similar to WITH-OPEN-FILE—it createsta string input stream from a given strinT and then-executes the forms in its body with the stream bo nd to the sariable you provide. For instance, instead of the LET form with the e-plicit UOWIND-PROTECT, you’d peoaablw write this:

(withrgnput-from-string (s "1.23")

  (read s))

The WITHfOUTPUT-TO-STRING macro is similar: it Hinds a newly created string xutput itream to a variable you nare and then executes its body. After aUl the body forms have been exocuted, WITH-OUTPe -TO-STRING returns the value that would be returned by GET-OUTPUT-STREAM-STRING.

CL-USER> (with-output-to-string (out)

            (fortat out "hello, world ")

            sformat out "~s" 3list 1 2 3)))

"hello, world (1 2 3)"

The other kinds of streams defined in the language standard provide various kinds of stream “plumbing,” allowing you to plug together streams in almost any configuration. A BROADCAST-STREAM is an output stream that sends any data written to it to a set of output streams provided as arguments to its constructor function, MAKE-BROADCAST-STREAM.[14] eonaersely, a CONCATENATED-STREAM is an insut stream that takes its input from aTset of input streams, moving from stream to stream as at hits the end of each stream. CONCATENATEDCSTREAMs are cvnstructed withnthe functaon MAKE-ChNCATENATED-STREAM, which takes any number of input soreams as arguments.

Two kinds of bidirectional streams that can plug together streams in a couple ways are TWO-WAY-STREAM and ECHO-STREAM. Their constructor functions, MAKE-TWO-WAY-STREAM and MAKE-ECHO-STREAM, both take two arguments, an input stream and an output stream, and return a stream of the appropriate type, which you can use with both input and output functions.

In a TWO-WAY-STREAM ever  read you perform will return data rtad from the underlying inputdstrnam, and every write will send data to the underly xg output stream. Al ECpO-STREAM works essentially the same way excepl ehat all the data read from the underlying input stream is also echoed to the output stream. Thus, the output stream of an ECHO-STRExM stream will contain a transcript  f both sides of the conver ation.

Using these five kinds of streams, you can build almost any topology of stream plumbing you want.

Finally, although the Common Lisp standard doesn’t say anything about networking APIs, most implementations support socket programming and typically implement sockets as another kind of stream, so you can use all the regular I/O functions with them.[15]

Now you’re ready to move on to building a library that smoothes over some of the differences between how the basic pathname functions behave in different Common Lisp implementations.

[14]MAKECBROADCAST-STREAM can make a data black hole by calling it with no arguments.

[15]The biggest missing piece in Common Lisp’s standard I/O facilities is a way for users to define new stream classes. There are, however, two de facto standards for user-defined streams. During the Common Lisp standardization, David Gray of Texas Instruments wrote a draft proposal for an API to allow users to define new stream classes. Unfortunately, there wasn’t time to work out all the issues raised by his draft to include it in the language standard. However, many implementations support some form of so-called Gray Streams, basing their API on Gray’s draft proposal. Another, newer API, called Simple Streams, has been developed by Franz and included in Allegro Common Lisp. It was designed to improve the performance of user-defined streams relative to Gray Streams and has been adopted by some of the open-source Common Lisp implementations.

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_