| Input and Output Streams

## Using Streams to Concatenate Files

> The SequenceInputStream creates a single input stream from multiple input sources. This example program, Concatenate, uses SequenceInputStream to implement a concatenation utility that sequentially concatenates files together in the order they are listed on the command line.

> This is the controlling class of the Concatenate utility:

> >     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);
> >             }
> >         }
> >     }

> The first thing that the Concatenate utility does is create a ListOfFiles object named `mylist` which is initialized from the command line arguments entered by the user. The command line arguments is a list of the files to be concatenated together. `mylist` is used to initialize the SequenceInputStream which uses `mylist` to get a new InputStream for every filename listed by the user.

> >     import java.util.*;
> >     import java.io.*;

> >     class ListOfFiles implements Enumeration {

> >         String[] listOfFiles;
> >         int current = 0;

> >         ListOfFiles(String[] listOfFiles) {
> >             this.listOfFiles = listOfFiles;
> >         }

> >         public boolean hasMoreElements() {
> >             if (current < listOfFiles.length)
> >                 return true;
> >             else
> >                 return false;
> >         }

> >         public Object nextElement() {
> >             InputStream is = null;

> >             if (!hasMoreElements())
> >                 throw new NoSuchElementException("No more files.");
> >             else {
> >                 try {
> >                     String nextElement = listOfFiles[current];
> >                     current++;
> >                     is = new FileInputStream(nextElement);
> >                 } catch (FileNotFoundException e) {
> >                     System.out.println("ListOfFiles: " + e);
> >                 }
> >             }
> >             return is;
> >         }
> >     }

> ListOfFiles implements the Enumeration interface. You'll see how this comes into play as we walk through the rest of the program.

> After the `main()` method creates the SequenceInputStream, it reads from it a byte at a time. When the SequenceInputStream needs an InputStream from a new source (such as for the first byte read or when it runs off the end of the current input stream), it calls `nextElement()` on the Enumeration object to get the next InputStream. ListOfFiles creates FileInputStream objects lazily, meaning that whenever SequenceInputStream calls `nextElement()`, ListOfFiles opens a FileInputStream on the next filename in the list and returns the stream. When the ListOfFiles runs out of files to read (it has no more elements), `nextElement()` returns null, and the call to SequenceInputStream's `read()` 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 which are used as input to other examples in this lesson.

> #### See Also

> > java.io.SequenceInputStream

| Input and Output Streams