2.11.3 Advanced Topic: Streams and Low-Level Input and Output
Files and pipes are both examples of general Mathematica objects known as streams. A stream in Mathematica is a source of input or output. There are many operations that you can perform on streams.
You can think of >> and << as "high-level" Mathematica input-output functions. They are based on a set of lower-level input-output primitives that work directly with streams. By using these primitives, you can exercise more control over exactly how Mathematica does input and output. You will often need to do this, for example, if you write Mathematica programs which store and retrieve intermediate data from files or pipes.
The basic low-level scheme for writing output to a stream in Mathematica is as follows. First, you call OpenWrite or OpenAppend to "open the stream", telling Mathematica that you want to write output to a particular file or external program, and in what form the output should be written. Having opened a stream, you can then call Write or WriteString to write a sequence of expressions or strings to the stream. When you have finished, you call Close to "close the stream".
Streams in Mathematica.
When you open a file or a pipe, Mathematica creates a "stream object" that specifies the open stream associated with the file or pipe. In general, the stream object contains the name of the file or the external command used in a pipe, together with a unique number.
The reason that the stream object needs to include a unique number is that in general you can have several streams connected to the same file or external program at the same time. For example, you may start several different instances of the same external program, each connected to a different stream.
Nevertheless, when you have opened a stream, you can still refer to it using a simple file name or external command name so long as there is only one stream associated with this object.
This opens an output stream to the file tmp.
In:= stmp = OpenWrite["tmp"]
This writes a sequence of expressions to the file.
In:= Write[stmp, a, b, c]
Since you only have one stream associated with file tmp, you can refer to it simply by giving the name of the file.
In:= Write["tmp", x]
This closes the stream.
Here is what was written to the file.
Low-level output functions.
When you call Write[stream, expr], it writes an expression to the specified stream. The default is to write the expression in Mathematica input form. If you call Write with a sequence of expressions, it will write these expressions one after another to the stream. In general, it leaves no space between the successive expressions. However, when it has finished writing all the expressions, Write always ends its output with a newline.
This re-opens the file tmp.
In:= stmp = OpenWrite["tmp"]
This writes a sequence of expressions to the file, then closes the file.
In:= Write[stmp, a^2, 1 + b^2]; Write[stmp, c^3]; Close[stmp]
All the expressions are written in input form. The expressions from a single Write are put on the same line.
"a^21 + b^2
Write provides a way of writing out complete Mathematica expressions. Sometimes, however, you may want to write out less structured data. WriteString allows you to write out any character string. Unlike Write, WriteString adds no newlines or other characters.
This opens the stream.
In:= stmp = OpenWrite["tmp"]
This writes two strings to the stream.
In:= WriteString[stmp, "Arbitrary output.\n", "More output."]
This writes another string, then closes the stream.
In:= WriteString[stmp, " Second line.\n"]; Close[stmp]
Here are the contents of the file. The strings were written exactly as specified, including only the newlines that were explicitly given.
More output. Second line."
Writing output to lists of streams.
An important feature of the functions Write and WriteString is that they allow you to write output not just to a single stream, but also to a list of streams.
In using Mathematica, it is often convenient to define a channel which consists of a list of streams. You can then simply tell Mathematica to write to the channel, and have it automatically write the same object to several streams.
In a standard interactive Mathematica session, there are several output channels that are usually defined. These specify where particular kinds of output should be sent. Thus, for example, $Output specifies where standard output should go, while $Messages specifies where messages should go. The function Print then works essentially by calling Write with the $Output channel. Message works in the same way by calling Write with the $Messages channel. Section 2.13.1 lists the channels used in a typical Mathematica session.
Note that when you run Mathematica through MathLink, a different approach is usually used. All output is typically written to a single MathLink link, but each piece of output appears in a "packet" which indicates what type it is.
In most cases, the names of files or external commands that you use in Mathematica correspond exactly with those used by your computer's operating system. On some systems, however, Mathematica supports various streams with special names.
Special streams used on some computer systems.
The special stream "stdout" allows you to give output to the "standard output" provided by the operating system. Note however that you can use this stream only with simple text-based interfaces to Mathematica. If your interaction with Mathematica is more complicated, then this stream will not work, and trying to use it may cause considerable trouble.
Some options for output streams.
You can associate a number of options with output streams. You can specify these options when you first open a stream using OpenWrite or OpenAppend.
This opens a stream, specifying that the default output format used should be OutputForm.
In:= stmp = OpenWrite["tmp", FormatType -> OutputForm]
This writes expressions to the stream, then closes the stream.
In:= Write[stmp, x^2 + y^2, " ", z^2]; Close[stmp]
The expressions were written to the stream in OutputForm.
" 2 2 2
x + y z"
Note that you can always override the output format specified for a particular stream by wrapping a particular expression you write to the stream with an explicit Mathematica format directive, such as OutputForm or TeXForm.
The option PageWidth gives the width of the page available for textual output from Mathematica. All lines of output are broken so that they fit in this width. If you do not want any lines to be broken, you can set PageWidth -> Infinity. Usually, however, you will want to set PageWidth to the value appropriate for your particular output device. On many systems, you will have to run an external program to find out what this value is. Using SetOptions, you can make the default rule for PageWidth be, for example, PageWidth :> <<"!devicewidth", so that an external program is run automatically to find the value of the option.
This opens a stream, specifying that the page width is 20 characters.
In:= stmp = OpenWrite["tmp", PageWidth -> 20]
This writes out an expression, then closes the stream.
In:= Write[stmp, Expand[(1 + x)^5]]; Close[stmp]
The lines in the expression written out are all broken so as to be at most 20 characters long.
"1 + 5*x + 10*x^2 +
10*x^3 + 5*x^4 +
The option CharacterEncoding allows you to specify a character encoding that will be used for all strings containing special characters which are sent to a particular output stream, whether by Write or WriteString. You will typically need to use CharacterEncoding if you want to modify an international character set, or prevent a particular output device from receiving characters that it cannot handle.
Manipulating options of streams.
This opens a stream with the default settings for options.
In:= stmp = OpenWrite["tmp"]
This changes the FormatType option for the open stream.
In:= SetOptions[stmp, FormatType -> TeXForm];
Options shows the options you have set for the open stream.
This closes the stream again.
Manipulating options for the standard output channel.
At every point in your session, Mathematica maintains a list Streams[ ] of all the input and output streams that are currently open, together with their options. In some cases, you may find it useful to look at this list directly. Mathematica will not, however, allow you to modify the list, except indirectly through OpenRead and so on.
THIS IS DOCUMENTATION FOR AN OBSOLETE PRODUCT.
SEE THE DOCUMENTATION CENTER
FOR THE LATEST INFORMATION.