The Java TM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search

Trail: Essential Java Classes
Lesson: Reading and Writing (but no 'rithmetic)

## How 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.*;

> >     public class Concatenate {
> >         public static void main(String[] args) throws IOException {
> >             ListOfFiles mylist = new ListOfFiles(args);

> >             SequenceInputStream s = new SequenceInputStream(mylist);
> >             int c;

> >             while ((c = s.read()) != -1)
> >                System.out.write(c);

> >             s.close();
> >         }
> >     }

> 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 list 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.*;

> >     public class ListOfFiles implements Enumeration {

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

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

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

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

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

> 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 one 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.

| Start of Tutorial > Start of Trail > Start of Lesson | Search