![]() ![]() ![]() ![]() |
Input and Output Streams |
This page illustrates how to use the many of java.io input and output streams through the use of several examples. Click on the links below to get to the section you're interested in:
- Using Piped Streams
- Using Streams to Read and Write Files
- Using Streams to Read and Write Memory Locations
- Using Streams to Concatenate Files
Using Piped Streams
The java.io package contains two classes, PipedInputStream and PipedOutputStream, that implements the input and output components of a pipe. Pipes are used to channel the output from one program (or thread or code block) into the input of another. A PipedOutputStream must be connected to a PipedInputStream and vice versa.Piped input and output streams are convenient for methods that produce output to be used as input by someone else. For example, suppose that you were writing a class that implemented various text utilities such as sorting, extracting unique lines, and reversing text. It would be nice if (IWBNI) the output of one of these methods could be used as the input for another. Thus you could string a series of these methods together to perform some function. The pipe shown here uses reverse, sort, and reverse on a list of words to create a list of rhyming words.
Without piped streams, you would have to create temporary files between each step:list of words -> reverse -> sort -> reverse -> rhyming wordsLet's look at a class that implements the reverse and sort methods using piped streams and a test program that uses the reverse and sort methods in the pipe shown above to generate a list of rhyming words.list of words -> reverse -> tmpfile tmpfile -> sort -> tmpfile2 tmpfile2 - > reverse -> rhyming wordsFirst, the StringUtils class contains two methods,
reverse()
andsort()
, designed to be used in a pipe. Bothreverse()
andsort
read data from an InputStream, process it (either reversing the strings within it, or sorting it, and produce a PipedInputStream suitable for another method to read. Let's look in detail atreverse()
; thesort()
method is very similar toreverse()
and doesn't warrant it's own discussion.Thepublic static InputStream reverse(InputStream source) { PipedOutputStream ps = null; PipedInputStream is = null; try { DataInputStream dis = new DataInputStream(source); String input; ps = new PipedOutputStream(); is = new PipedInputStream(ps); PrintStream os = new PrintStream(ps); while ((input = dis.readLine()) != null) { os.println(reverseString(input)); } os.close(); } catch (Exception e) { System.out.println("StringUtils reverse: " + e); } return is; }reverse()
method takes an InputStream which contains a list of strings to be reversed.reverse()
maps a DataInputStream onto thesource
InputStream so that it can use the DataInputStream'sreadLine()
method to read each line from the file.Next,
reverse()
creates a PipedOutputStream and connects a PipedInputStream to it. Remember that a PipedOutputStream must be connected to a PipedInputStream and vice versa. Thenreverse()
maps a PrintStream onto the PipedOutputStream so that it can use the PrintStream'sprintln()
method to write strings to the PipedOutputStream.Now,
reverse()
reads the input line by line from thesource
stream, reverses each line using thereverseString()
method, and then writes the reversed string to the PipedOutputStream.When
reverse()
closes the PipedOutputStream, all the data written to the PipedOutputStream, gets flused into the PipedInputStream connected to it. The PipedInputStream is now filled with a list of words that have been reversed and is primed for reading by another method, program or thread.reverse()
returns the PipedInputStream for use by the calling program.The
sort()
method follows the same pattern:Calls to
- open piped output stream
- connect piped input stream to it
- write to the piped output stream
- close the piped output stream
- hand the now-full piped input stream to someone else to read
reverse()
andsort()
can be cascaded together so that the output from one method can be the input for the next method. In fact, the test program RhymingWords does just that, cascading calls toreverse()
,sort()
, and thenreverse()
to generate a list of rhyming words:When you run RhymingWords on this file of words you will see this output:DataInputStream words = new DataInputStream(new FileInputStream("words")); InputStream rhymedWords = StringUtils.reverse(StringUtils.sort(StringUtils.reverse(words)));If you look closely you can see that "rhyming" words such as environment, development, argument and component are grouped together.Java interface image language communicate integrate native string network stream program application animation exception primer container user graphics threads tools class bolts nuts object applet environment development argument component input output anatomy securityUsing Streams to Read and Write Files
File streams are perhaps the easist streams to understand. Simply put, FileInputStream (FileOutputStream) represent an input (output) stream on a file that lives on the native file system. You can create a file stream from the filename, a File object or a FileDescriptor object. Use these streams to read data from or write data to files on the file system.This small example uses the file streams to copy the contents of one file into another.
import java.io.*; class FileStreamsTest { public static void main(String args[]) { try { FileInputStream fis = new FileInputStream("farrago.txt"); FileOutputStream fos = new FileOutputStream("outagain.txt"); int c; while ((c = fis.read()) != -1) { fos.write(c); } fis.close(); fos.close(); } catch (FileNotFoundException e) { System.err.println("FileStreamsTest: " + e); } catch (IOException e) { System.err.println("FileStreamsTest: " + e); } } }Using Streams to Read and Write Memory Locations
Use ByteArrayInputStream and ByteArrayOutputStream to read and write 8-bit data. You create these streams on an existing byte array and then use theread()
andwrite()
methods to read from or write data to the array in memory. Other streams operate on Unicode data.Use StringBufferInputStream to read data from a StringBuffer. You create stream on an existing StringBuffer object and then use the
read()
methods to read from StringBuffer as it lives in memory. This stream is similar to the ByteArrayInputStream which reads 8-bit data from a byte array in memory. StringBufferInputStream reads 16-bit Unicode data from a string buffer in memory.[PENDING: write example for one of these.]
Using Streams to Concatenate Files
The SequenceInputStream creates a single input stream on multiple input sources. This example program, Concatenate implements a concatenation utility similar to Unix'scat
command-- it concatenates files together in the order they are listedon the command line.This is the main program of the Concatenate utility:
Concatenate creates a ListOfFiles object from the filenames listed on the command line by the user. ListOfFiles is an Enumeration that maintains a list of the filenames the user wishes to concatenate together. An Enumeration object is needed to create the SequenceInputStream. This Enumeration object, the ListOfFiles object in our example, provides a series of InputStreams to the SequenceInputStream as needed.import java.io.*; class Concatenate { public static void main(String args[]) { ListOfFiles mylist = new ListOfFiles(args); try { SequenceInputStream s = new SequenceInputStream(mylist); int c; while ((c = s.read()) != -1) { System.out.write(c); } s.close(); } catch (IOException e) { System.err.println("Concatenate: " + e); } } }After the
main()
method creates the SequenceInputStream, it reads from the stream a byte at a time. Whenever the SequenceInputStream runs off the end of one InputStream in the Enumeration, it callsnextElement()
on the Enumeration object to get the next one. ListOfFiles creates FileInputStream objects lazily, meaning that whenever SequenceInputStream callsnextElement()
ListOfFiles opens a FileInputStream on the next filename and returns the stream. When the ListOfFiles runs out of files to read (it has no more elements) the call to SequenceInputStream'sread()
method returns -1 to indicate the end of input.Concatenate simply echos all the data read from the SequenceInputStream to the standard output.
Try this: Try running Concatenate on the
farrago.txt
and words.txt files used as input to other examples in this lesson.See Also
java.io.PipedInputStream
java.io.PipedOutputStream
java.io.FileInputStream
java.io.FileOutputStream
![]() ![]() ![]() ![]() |
Input and Output Streams |