Survey of the IO Classes


Peter Komisar 
©   Conestoga College   latest version   5.8 /  2010


IO Class Categorization


As we saw last section, the input and output streams
of the IO package follow a logical naming scheme related
to whether they are input or output classes , what function
they serve, and whether they deal with 8 or 16-bit primitive
types.

// in or out, 8 or 16 & function

This group further subdivides to low and high level streams.
Low level streams open on data sources or destinations,
while high level streams open on low-level streams. (High
and low level are also called high and low order streams.)

// high level streams open on low-level streams

In addition to these stream classes there are special classes
like the File class, RandomAccessFile and StreamTokenizer
that have unique abilitites. The package also houses the
exception classes that are related directly to input and output
functions.

// package holds special function classes & exception classes

The tables below categorize the IO classes along the lines
just described. Notice there is not perfect symetry across
the categories. Sometimes stream classes fall into one or
two categories instead of having a version in all four general
divisions.
 

Categorizing the Classes of the java.io Package

The following tables list classes of the java.io package in
categories based on different classification criteria.

8-Bit Input / Output Stream Classes

      Low Level InputStreams   Low Level OutputStreams
 
 FileInputStream

 ByteArrayInputStream
 PipedInputStream

  FileOutputStream
 
ByteArrayOutputStream
  PipedOutputStream
 High Level InputSteams   HighLevel OutputStreams

 BufferedInputSteam
 
DataInputStream
 
PushbackInputStream

 BufferedOutputStream
 DataOutputStream

 PrintStream


 16-Bit Reader / Writer Classes

     Low Level Readers    Low Level  Writers

 FileReader

 CharArrayReader
 PipedReader
 StringReader

 FileWriter
 CharArrayWriter

 PipedWriter
 StringWriter
 High Level Readers  High level Writers
 
 BufferedReader

 PushbackReader

 LineNumberReader

 BufferedWriter
 PrintWriter

 
Specialty Classes

 Unique Stream Classes  Non-stream  classes
 SequenceStreamReader
 
InputStreamReader
 OutputStreamWriter
 
ObjectInputStream
 
ObjectOutputSteam
 
StreamTokenizer
 
 File

 FileDescriptor

Bii-directional random access class

RandomAccessFile
 


Low-Level Stream Classes

First we survey the low-order streams. These open on specific
sources and destinations.
These include files, arrays, strings
and piped streams.

 
 
 
 FileInputStream
 
FileOutputStream
 FileReader
 
FileWriter

 - a byte-based input stream that reads from a file
  -
a byte-based output stream that writes to a file

 - a character-based stream for reading from a file
 - a character-based stream for writing to a file
 
 ByteArrayInputStream
 
ByteArrayOutputStream
 CharArrayReader
 
CharArrayWriter

 - takes input from a byte array or an array subset
 - writes to a byte array or an array subset

 - reads characters from a character array
 - writes characters to a character array
  No corresponding
  8-bit streams -note->

 StringReader
 StringWriter

   // StringBufferInput/OutputStream deprecated
   // problems translating characters to bytes
 - reads characters from a String supplied to constructor
 - writes characters to a string buffer (not to String)
 

 PipedInputStream

 PipedOutputStream

 PipedReader
 
PipedWriter
 
 - reads bytes from an attached piped output stream
 - writes bytes to an attached piped input stream

- reads characters written to an attached piped writer

 - writes characters to an attached piped reader


// Piped streams are used for inter-thread communication in multithreaded environments.

// Piped streams can replace wait( )/notify( ) in the classic producer/consumer scenario.
 

High-Level Stream Classes // Take their input from other streams
 
 BufferedInputStream
 BufferedOutputStream

 BufferedReader

 BufferedWriter

 - uses an internal array to buffer data read from source

 - collects data in buffer until full then writes in one operation
 - uses an internal array to buffer data read from source
 - collects data in a buffer until full then writes in one operation

 
 DataInputStream

 DataOutputStream

 
No Reader version
 
No Writer version

 - reads input stream bytes & converts to Java primitives 
 - converts Java primitive to output stream bytes
   // no need for 16 bit version.

   // just deals with primitives and bytes
 
  LineNumberReader

  No InputStream or
  Writer counterpart
 
 - maintains a count of lines read,
 - sub-classes
BufferedReader
  // LineNumberInputStream is deprecated
 
 PrintStream

 PrintWriter
 
Outbound Classes

 - supports easy writing of text to output 
 - like PrintStream but defines char based methods
   // No input counterparts
 
 PushbackInputStream

 PushbackReader

  No OutputStream
  or Writer counterpart

 - allow byte(s) read to be pushed back to source
 
- allow char(s) to be pushed back to source
    // both use internal stacks
 
 SequenceInputStream

 - concatenates two or more input streams 
 
 InputStreamReader

 OutputStreamWriter

 Adapter classes

 - reads bytes and converts them to chars
 - takes chars and converts to a stream of bytes

 
// Convert between the 8 and 16-bit stream types
 
 ObjectInputStream
 ObjectOutputStream
 No Reader/Writer Types

 - reads serialized objects from stream
 - writes serialized objects to stream

 // objects are serialized to stream in bytes


The stream classes described in these tables follow for the most
part the same patterns of usage we described in our earlier note.
We also will look at a few of the more specialized classes like File,
RandomAccessFile and StreamTokenizer in the following examples.


Using FileWriter


To write a String or an array to file, FileWriter offers easy to
use, overidden versions
of write that take an array or a String.
Commented out is an alternate way of writing
a String to file
using the FileOutputStream class in conjunction with PrintWriter.

Sample showing FileWriter 's Economic Use of Code

import java.io.*;

class Xray {
public static void main(String[]args){
String message="London England Moscow Russia Rome Italy";

// File Writer does it with less code

// FileOutputStream fos=null;
// PrintWriter pw;

try{

// fos=new FileOutputStream("XAX");
// pw=new PrintWriter(fos);
// pw.println(message);
// pw.close( );
// fos.close( );

FileWriter fw=new FileWriter("SOS");
fw.write(message);
fw.close( );

// Console output to explain what has happened
System.out.println("The message was written to File 'SOS'.");

 }
 catch(IOException io){ System.out.println( io.toString( )); }
}
}

Form of a read loop

Often you'll want to read everything from a file into a program.
A loop is the easy way to do this. In streaming though, one
needs to be careful to not skip a byte being read when doing
an evaluation to see if it is the last byte. A way to avoid this
problem is to assign return value of the the byte read( ) function
to a variable inside the while loops argument area.

In the next example the inner brackets allows the assignment
to take place before the evaluation occurs. The -1 signifies the
end of file or EOF.


Example  
      

while ( ( c = in.read( ) ) ! = -1 )
System.out.println( c );


The following short code sample shows the while loop being
used in this form. (Try with a file called Zee.txt with the String
ABCDEFG stored in it.)


While Loop read( ) Sample

import java.io.*; 

class ReadLoop {
public static void main(String[]args){
int symbol=0;
FileInputStream fis=null;
 try{
    fis=new FileInputStream("Zee.txt");
    while( (symbol=fis.read( ))!= -1){
      System.out.print((char)symbol + "-");
      }
    }
  catch(FileNotFoundException fnfe){}
  catch(IOException io){}
  }
}

OUTPUT

A-B-C-D-E-F-G-H-I-J-


To demonstrate why it is neccessary to capture each read
before testing for the EOF symbol we can used the following
code which effectively loses one turn on each read as the
loop evaluation loses one of the characters read.
 

Sample Showing Reading Without Character Capture

import java.io.*;
 

class ReadLoop {
public static void main(String[]args){
int symbol=0;
FileInputStream fis=null;
 try{
    fis=new FileInputStream("Zee.txt");
    while(fis.read( ) != -1){
      symbol=fis.read( );
      System.out.print((char)symbol + "-");
      }
    }
  catch(FileNotFoundException fnfe){}
  catch(IOException io){}
  }
}

OUTPUT

B-D-F-H-J-

Every second letter has been sacrificed in the
while loop to test for -1.


File Class


In Java, file meta-data, (information about a given file but
not it's contents) is returned by methods of the File class.
The File class doesn't itself do any IO. What follows is a
summary of some of the work that the File class can do
along with a table describing of some of it's methods.

Some Tasks File Class Can Perform

1) returns a File object which a file can be opened on.
2) tests if a file exists, or can be read/write
3) tests whether a File object represents a file or a directory
4) returns # bytes and when file was last modified
5) has methods to create and delete files and directories

Some of File's methods // see jdk API  for fuller descriptions
 
 public int
compareTo

(java.io.File)
 lexigraphical comparison < = = >
 public static File 
 createTempFile
 (String1, String2, File) 
 throws IOException
 File is dir where temp file will be created 
 String1-->file name prefix 
 String2--> suffix (min.3 chars long)
public void
deleteOnExit( ); 
 marks file to be deleted when program
 ends
(can't rescind call)
 public boolean
 mkdir( ) 
 creates one directory
 public boolean
 mkdirs( ) 
 as mkdir( ) plus any needed parent
 directories
 String[] list( );  returns a String array [of files & dirs] contained 
 in the dir from which the method has been invoked
 File[] listFiles( );  same as list( ) but returns File objects not String
 listRoots( )  lists the available filesystem roots
 (i.e. "A:\", "C:\" etc.) 
 URL toURL( ) throws 
 MalformedURLException
 puts File object into URL form  (file:/// something)
 (if the File object is a directory it end's in a slash "/")
 public boolean 
 createNewFile( )
 throws  java.io.Exception
 creates a new file if it doesn't already exist and
 returns boolean if a new file has been created.


File Class in Code

The first example is short and is provided to show the
mkdirs( )  method in action.

File mkdirs( ) method in Code

import java.io.*;

class MK{
public static void main(String[]args){
File f =new File("X/Y/Z");
System.out.println("All Directories Created: " + f.mkdirs());
}
}

OUTPUT

> java MK
All Directories Created: true


A Bigger File Class Example

The next code sample class shows a number of File
methods. It uses a recursive method for traversing
a directory that  can be found in the 'Java Certification
Study Guide' written by Heller & Roberts. A second
functionality is added to show information that the File
class can provide for a single file.

The java.util package supplies the Date class which can
be used to return the number of milliseconds that have
transpired since the beginning of 1970. Between the
getTime( ) method of the Date class and the File class
method, lastModified( ),the amount of time that has
transpired since the last time the file was modified can
be deduced. Notice the file report will only say a file
exists if it is found in the same directory.

A Fix that was Fixed


There is a fix in the following code that doesn't seem to be necessary in more recent releases of Java. Scrolling would sometimes leads to bad painting. To
fix this, a reference to JViewport was obtained using the getViewport( ) method.
A change listener was added to it. From the ChangeListener's stateChanged( )
method a repaint has been called on the text area and the painting is good regardless of how extremely the view is scrolled.

But now it seems it has no effect, perhaps because systems are quicker now.



The following code builds a GUI over code found in 'Java Certification
Study
Guide' Heller & Roberts, Sybex.


File Class Code Sample

import java.awt.*;
import java.io.File;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.event.*;

public class NewLister extends JFrame
implements ActionListener,ChangeListener{
JTextField tf1,tf2;
JTextArea ta;
// main instantiates class
public static void main(String args[]){

  NewLister lister=new NewLister();
  }
 // visual build in constructor

NewLister( ){
  ta=new JTextArea();
  JScrollPane sp=new JScrollPane(ta);
  JViewport view=sp.getViewport();
  view.addChangeListener(this);
  ta.setFont(new Font("Monospaced",Font.PLAIN,12));
  getContentPane().add(BorderLayout.CENTER,sp);

  JPanel dir=new JPanel();
  dir.setLayout(new FlowLayout(FlowLayout.LEFT));
  JLabel dirlabel=new JLabel("Enter a directory",SwingConstants.CENTER);
  dir.add(dirlabel);
  tf1=new JTextField(" Enter a directory     ", 52);
  tf1.addActionListener(this);
  tf1.setFont(new Font("Monospaced",Font.PLAIN,14));
  dir.add(tf1);

  JLabel fill=new JLabel("               ");
  dir.add(fill);
  dir.add(tf1);
  getContentPane().add(BorderLayout.NORTH,dir);
  JPanel file=new JPanel();
  file.setLayout(new FlowLayout(FlowLayout.LEFT));
  JLabel filelabel=new JLabel("Pick a file in the directory     ",SwingConstants.CENTER);
  tf2=new JTextField("  Enter a file name for file details  ",50);
  tf2.addActionListener(this);
  tf2.setFont(new Font("Monospaced",Font.PLAIN,14));
  file.add(filelabel);
  file.add(tf2);
  JLabel fill2=new JLabel("               ");
  dir.add(fill2);
  getContentPane().add(BorderLayout.SOUTH,file);
  setSize(700,450);
  setVisible(true);
  }
//action method
public void actionPerformed(ActionEvent ae){
if(ae.getSource().equals(tf2)){
   String name=tf2.getText();
   File f2=new File(name);
     if(f2.isDirectory()){
       tf2.setText("Doesn't exist or is a directory");
       }
   else{
     try{
       String report=
       " The file exists: " + f2.exists() +
       "\n The absolute path is: " + f2.getAbsolutePath()  +
       "\n The canonical path is: " + f2.getCanonicalPath( ) +
       "\n A hashCode for this pathname: " + f2.hashCode() +
       "\n This is a directory: " + f2.isDirectory() +
       "\n This is a file: " + f2.isFile( ) +
       "\n This is a hidden file: " + f2.isHidden() +
       "\n This file was last modified(in days): " +
        lastMod(f2.lastModified()) +
       "\n This file length is: " + f2.length();
        ta.setText(report);
        }
        catch(IOException io){
        io.printStackTrace();
        }
      }
   }
  if(ae.getSource().equals(tf1)){
     ta.setText("");
     String name=tf1.getText();
     File f2=new File(name);
  if(!f2.isDirectory()){
     System.out.println("Doesn't exist or not a path");
     ta.setText("Doesn't exist or not a path");
     }
    else{
        recurse(f2,0);
        repaint();
        }
     }
   }
// change listener fixes painting in slow systems
public void stateChanged(ChangeEvent e){
  ta.repaint( );
  }
// a  method to calculate time elapsed from day last modified to today
  long lastMod(long mls){
     long today =new Date( ).getTime( );
     System.out.println(today);
     long days= (today - mls) / (1000 * 60 * 60 * 24);
     System.out.println(mls);
     System.out.println(days);
     return days;
     }
// Heller & Roberts recurse( ) method from the Java Certification Study Guide
void recurse(File dirfile, int depth){
  String contents[]=dirfile.list( );
  for (int i=0; i<contents.length; i++) {
    for (int spaces=0; spaces<depth; spaces++)
      ta.append("     ");
  ta.append(contents[i] + "\n");
  File child=new File(dirfile,contents[i]);
  if (child.isDirectory())
  recurse(child,depth+1);
   }
 }
}

FileDescriptor     // just for reference

Instances of the file descriptor class serve as an 'opaque' handle
to the underlying machine-specific structure representing an open
file, an open socket, or another source or sink of bytes. The main
practical use for a file descriptor is to create a FileInputStream or
FileOutputStream to contain it.

JDK Documentation states that applications should not create
their own file descriptors.
 


RandomAccessFile


RandomAccessFile is a unique and powerful class. Where most
of the stream classes implement input or output interfaces, the
RandomAccessFile implements both functionalities. Because of
the way it is built it cannot be layered in streams like other stream
classes. RandomAccessFile has the reading and writing methods
of DataInputStream and DataOutputStream combined.

RandomAccessFile has a file pointer that can be used to find a
location inside a file at any offset point.

// RandomAccessFile can create files

RandomAccessFile can create files just by specifying them in it's
constructor, whether the file existed before or not. (This is a capability
of FileOutputStream and FileWriter as well. ) The constructor also
specifies if the file is read or read write. The constructors can take
files specified by their String name or as File objects. The mode is
read or read-write and is specified with String literals, "r" or "rw".


Constructor Form 1       

RandomAccessFile(File file, String mode)
// mode is  "r" or "rw" , takes a file object

Constructor Form 2
        

RandomAccessFile(String name, String mode)
 // takes a String representation of a File name.

The RandomAccessFile class defines the methods, seek( ) and
getFilePointer( ) to point at locations inside a file. The seek( )
method
takes a long value and sets the position of the file pointer
so a specific location
in a file can be accessed. The getFilePointer( )
method will return a long value
representing the location where the
file pointer is located.

The seek( ) method will throw an IOException if the a value less
than zero is selected  or a value whichis greater than the length
of the file.


Special RandomAccessFile methods

void seek( long position ) 
// sets the position of the file pointer.


long getFilePointer( )       

// returns the current location of the file pointer


The following RandomAccessFile Code sample creates a text
area in a JFrame. A RandomAccessFile object is created on a
File object. The File object is opened on a file on the system.
The length method of the File class is used to control the number
of times bytes are read from the file. In each turn through the loop
the byte read is appended to the text displayed in the text area.
To show how seek( ) works, arbitrary positions in the stream are
printed to console.

// seek uses offset values reads absolute positions


RandomAccessFile Code Sample

import java.io.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

class Random{

     public static void main(String[] args){
     int i=0;
     RandomAccessFile raf=null;
     if(!(args.length>0)){
       System.out.println
       ("Enter a file name at the command line");
       System.exit(0);
        }
      String name=args[0];
     JFrame frame=new JFrame( );

     JTextArea jta=new JTextArea( );
     jta.setFont(new Font("Monospaced",Font.PLAIN,12));
     frame.getContentPane().add(jta);
     try{
       File file=new File(name);
       raf=new RandomAccessFile(file,"rw");
     for(int z=0;z<file.length();z++){
       i=raf.readByte();
      // this bit of logic keeps the index numbers visually formatted
       if(z<10)
       jta.append(" " +z+ "   :    " + (char)i + "\n");
       else
       jta.append( z + "   :    " + (char)i + "\n");
       }
     }
     catch(FileNotFoundException fnfe){
     fnfe.printStackTrace();
     }
     catch(IOException io){
     io.printStackTrace();
     }

// these writes are back at the command line console
// note the file pointer is set to one more than the seek value

  try{
     raf.seek(0);
     System.out.println("" +(char)raf.readByte());
     System.out.println("File Pointer is at: " + raf.getFilePointer());
      raf.seek(5);
     System.out.println("" +(char)raf.readByte());
     System.out.println("File Pointer is at: " + raf.getFilePointer());
       raf.seek(12);

     frame.setVisible(true);
     System.out.println("" +(char)raf.readByte());
     System.out.println("File Pointer is at: " + raf.getFilePointer());
      raf.seek(14);
     System.out.println("" +(char)raf.readByte());
     System.out.println("File Pointer is at: " + raf.getFilePointer());
     }

     catch(IOException io){}

     frame.setSize(200,500);
     frame.setVisible(true);
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

     }
 }


StreamTokenizer


StreamTokenizer parses input into tokens, usually from inside
a while loop, calling
nextToken( ) until the end of the input is
reached. Tokens are defined groups of
characters such as
words. The int returned by the nextToken( ) method describes
the type of
the next token, (as described by static fields such
as TT_NUMBER, TT_WORD,
TT_EOL, & TT_EOF)  Many
methods are available to recognize various user-
specified
characters. StreamTokenizer is particularly suited for parsing
Java, C or
C++.  Notice in the following table summary of
StreamTokenizer's fields that
non-static fields are lowercase.


StreamTokenizer's Field Summary
    //   from the JDK documentation
 
 double nval  If the current token is a number, this field
contains the 
value of that number.
 String sval  If the current token is a word token, this
field contains a
string giving the characters
of the word token.
static int TT_EOF  A constant indicating that the end of the
stream has been read.
static int TT_EOL  A constant indicating that the end of the
line has been read.
 static int TT_NUMBER  A constant indicating that a number token
has been read.
 static int TT_WORD  A constant indicating that a word token
has been read.
 int ttype  After a call to the nextToken method,
this field contains
the type of the token
just read.


StreamTokenizer has a deprecated constructor that opens
on an InputStream
object and preferred constructor that
opens on a Reader class. The recommended
way to convert
from input stream to a reader is as follows.

A StreamTokenizer Opening on a BufferedReader 

Reader r = new BufferedReader(new InputStreamReader(is));
StreamTokenizer st = new StreamTokenizer(r);


This is similar to how we used an input to send to console. The
technique is used below in the
code sample. The code opens
on a file with a FileInputStream which is then
set to standard
input. A Stream Tokenizer is then opened on the buffered reader

which is opened on the standard input. The stream tokenizer's
nextToken( ) method is used
to process each token until the end
of file symbol is reached. If the current token is
a word token, the
'sval' field of StreamTokenizer returns a String representing the
word
token.

Create a file 'Read.txt' that has words among numbers. The
program will filter word tokens from the text.

/* Today there is a new 45 combination that 7 is top secret 99
and will not be disclosed 22 to anyone! */

// text file is 'hard wired' into code sample


StreamTokenizer Code Sample

import java.io.*;

class Tokens
{
public static void main(String[]args)
   {
    int token;

  try{
         FileInputStream fi = new FileInputStream("Read.txt");
         System.setIn(fi);
         BufferedReader in=new BufferedReader
           (new InputStreamReader(System.in));
         StreamTokenizer st=new StreamTokenizer(in);

    while( (token=st.nextToken( ))!= StreamTokenizer.TT_EOF){
         if (st.sval != null)
         System.out.print(st.sval + " ");
         }
         in.close( );
     }
  catch(IOException io){
         System.out.println("IO Exception");
         }
     }
}

Note if the text and numbers is not clearly delineated
ambiguous variations may result. Consider the following
input and the resultant output. If a number appears within
a word then it is treated as part of the word. If a number
starts a word, the number is ignored and the following
letters are output.

/* b3 3b  77 word  * / 

OUTPUT

b3 b word

Following is a more elaborate version of the program that
filters both numerical values and word values and recomposes
them in groups. In this case an imaginary swiss bank account
number is interspersed inside a text file. The program retrieves
the account number from the file.

// Save the following text in a file called 'SwissCheese' . If you were really
// hiding a number somewhere
your might start with a much larger text body
// that is prescreened  for extraneous number
characters. 

/* This text 4 hides a 1 hidden 2 account
  9 9 number 0 for a Swiss 3 bank 5 account. */


import java.io.*;

class SwissTokens{
public static void main(String[]args){
  int token;
  // the array size is pre-set to the size needed for the imaginary swiss account

  int[] account = new int[8];

  try{  
         FileInputStream fi = new FileInputStream("SwissCheese");
         System.setIn(fi);
         BufferedReader in=new BufferedReader
         (new InputStreamReader(System.in));
         StreamTokenizer st=new StreamTokenizer(in);
      st.parseNumbers();
     
     int i = 0;
    while( (token=st.nextToken( ))!= StreamTokenizer.TT_EOF)
         { 
     // ttype is a non-static variable
         if (st.ttype==StreamTokenizer.TT_NUMBER)
       {
       account[i]= (int)Math.round(st.nval);
       i++;
       }
     if (st.sval!=null)
         System.out.print(st.sval + " ");
     }
     
     in.close( );
     fi.close( );
     
         System.out.print("\nThe number is: ");
     for (int j=0;j<account.length;j++){     
        System.out.print(account[j]);
        }
        System.out.println("");      
     }  
     catch(IOException io){
    System.out.println("IO Exception");
    }
  }
}

OUTPUT

This text hides a hidden account number for a Swiss bank account.
The number is: 41299035

 
StringTokenizer

 There is also a StringTokenizer but it is in the java.util package and not
 a part of the
java.io package  It might  be worth visiting for certain
 applications. The following  example
is from the JDK 1.3 documentation

  StringTokenizer st = new StringTokenizer("this is a test");
           while (st.hasMoreTokens( )) {
               println(st.nextToken( ));

               }
//  prints the following output:
          this
          is
          a
          test 




SequenceInputStream

SequenceInputStream provides a way for concatenating two or
more streams together.
It's constructors take either an enumeration
or two streams. To use the enumeration technique, separate
FileInputStream objects are added to a Vector. Then the Vector's
elements( ) method is called to return an enumeration. which is
then passed, in turn, as an argument to the SequenceInputStream
constructor.

The following code sample does all this, and then prints from the
resultant stream to prove the three files have been appended
together. You will have to supply the files if you wish to test this
code. 

// supply Apples.txt, Orange.txt & Plum.txt


The Invasion of Generics & the 'enum' type with JDK 1.5

Generics have invaded the typing system. You can expect the
compiler to be 'upset' if it is forced to determine object type at
runtime. The following code shows the new generic form applied
to Vector and the Enumeration type declaration.

There is also a new enum type added with JDK 1.5 as well,
which adds a major new data type to the language. It has put
the 'enum' keyword into full service in the Java language so
now we cannot call our enumeration an 'enum' as a result.


SequenceInputStream Code Example

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

class Sequence{
public static void main(String[]args){
  Vector<FileInputStream> vector;
  int character;
  try{
    FileInputStream a = new FileInputStream("Apple.txt");
    FileInputStream b = new FileInputStream("Orange.txt");
    FileInputStream c = new FileInputStream("Plum.txt");
    vector = new Vector<FileInputStream>( );
    vector.addElement(a);
    vector.addElement(b);
    vector.addElement(c);
    Enumeration<FileInputStream> enumeration=vector.elements();
    // can't use enum as an identifier
    // as enums are in as of JDK1.5
    SequenceInputStream sis=new SequenceInputStream(enumeration);

       while ( (character=sis.read()) != -1  ) {
                 System.out.print((char) character + "_");
                }
    }
    catch(IOException io){
    System.out.println("IO Exception");
    }
 }
}




Self Test                      Self Test With Answers


1 ) Which of  the following is not a low order io class?

a ) FileOutputStream
b) PipedInputStream
c) BufferedReader
d) ByteArrayOutputStream

2) Which of the following is not a high order class?

a) LineNumberReader
b) PipedReader
c) SequenceInputStream
d) DataInputStream

3) Which of the following is not an 16-bit stream
a) PipedWriter
b) BufferedReader
c) LineNumberReader
d) ObjectOutputStream

4 ) True or False. A File object can be created on a file name whether an
     underlying file exists on the system or not.
 

5) True or False. If a RandomAccessFile is opened on a non-existent file
    in read and write mode the file described will be created on the underlying
    system.

6 )Which class would be the best choice for writing ASCII characters to
     an array.

a) ByteArrayOutputStream
b) ByteArrayInputStream
c) CharArrayWriter
d) CharArrayReader


Exercise


Answer the following questions with brief but complete statements.

1 ) Create a command line program. Inside main
     add the following.

    File filo=new File("filo");
    boolean alive=filo.exists( );
    System.out.println("x is a file: " + alive);

Using the dir command first check if a file is created on the
underlying system.

a) Does the file exist.
b) Does the creation of a File object create a file on the
   underlying system?


2) Create a file with a sentence or two in it and enter it's
   name into the File constructor of the program you created
   in number 1. What does the exists( ) method now indicate
   regarding the file.

3) To the above program create a RandomAccessFile that
   opens on a non-existent file, something like "ZZZ.txt". 
   Set the second argument to read mode, "r". Will the compiler
  allow you to proceed? Does the program run? What happens?
  Check the underlying directory, was the file created?

4) Repeat the excercise in 3) this time setting the read-write
   attribute to read & write "rw". Will the compiler allow you to
   proceed? Does the program run? What happens? Check the
   underlying directory, was the file created?

5)  Now open the RandomAccessFile in the two modes on an
     existent file.
    
     a ) In read only mode did the program compile and run?
     b ) In read-write mode did the program compile and run?


Optional

6) Create a program that loads a file and uses File classes
length method, and RandomAccessFile's seek( ) method to
create a second file that stores the characters of the first
file in reverse order. Prove the conversion was successful,
by opening on the reverse ordered file and restoring it to it's
original condition.


How you might do this     
// only read if needed!

You may find how many characters there are using String's
length( ) method. In a descending loop, pass the counter to
the seek method to get each character. You could create a
String to which each character was appended and then write
the String to file in one go. Alternatively writing could be done
simultaneously from the loop to a FileOutputStream object.