10. Files and Streams

What We Will Cover


Illuminations

Questions on Completed Assignments?

10.1: Streams and File I/O

Objectives

At the end of the lesson the student will be able to:

  • Open streams and files
  • Differentiate between text and binary files
  • Recognize the benefits of buffering

10.1.1: About Program I/O

  • Program I/O = Program Input/Output
  • Input to and output from programs
  • Input can be from keyboard, network or file
  • Output can be to a display screen, printer, network or file
  • Note that files can be both input and output devices for programs
  • Advantages of file I/O
    • Data still exists after the program ends
    • Input can be automated (rather than entered manually)
    • Output from one program can be input to another
  • To store and retrieve data on a file, we need two items:
    • A file
    • A file stream object

10.1.2: Files

File: a collection of data stored under a common name on a storage medium other than a computer's main memory.

  • Files provide long-term storage of large amounts of data
  • Files stored on secondary storage devices
    • Magnetic disks
    • Optical disks
    • Other storage media
  • Files must have a name
  • Naming requirements depend on the underlying operating system (OS)
  • Typically, an OS limits the length of a file as shown in the following table
  • Operating System Maximum Length
    DOS 8+3
    Windows (after 95) 255
    Early UNIX 14
    Current UNIX) 255

  • Java views a file as a sequence of bytes
  • Byte 0 Byte 1 Byte 2 ... Byte n−1 End-of-file marker

  • File ends with an end-of-file marker or after a specific number of bytes

10.1.3: Streams

Stream: a one-way transmission path that either delivers data to a destination (screen, file, etc.) or that takes data from a source (keyboard, file, etc.)

  • Streams in Java are represented by objects
  • Input stream: an object that provides a sequence of bytes to a program
  • Output stream: an object that accepts a sequence of bytes from a program
  • A stream connects a program to an I/O object
  • System.out is an output stream
    • Connects a program to the display screen of your computer
    • Underlying stream object is called a PrintStream
  • System.in is an input stream
    • Connects a program to the keyboard
    • Underlying stream object is called an InputStream
  • We used System.in in lesson 2.4.2
  •    // set up for basic input stream
        InputStreamReader isr =
            new InputStreamReader(System.in);
        // need to use readLine()
        BufferedReader br = new BufferedReader(isr);
    
    

File Streams

File stream: a one-way transmission path used to connect a program to a file.

  • File streams can be either input or output streams
  • File input streams receive data from a file
  • File output streams send data to a file
  • Each file your program uses will need a separate file stream object

10.1.4: Types of Files

  • All data and programs are ultimately just zeros and ones
  • Each binary digit can have one of two values: 0 or 1
  • A bit is one binary digit
  • A byte is a group of eight bits
  • Java groups files into two broad categories: text and binary
  • Text Files

  • In text files, the bits represent printable characters
  • Files usually stored as one byte per character (ASCII)
  • Each byte is translated by display devices into readable characters
  • For example, Java source files are text files
  • Binary Files

  • Everything other than text is called binary
  • Each bit represents some type of encoded information
    • E.g.: program instructions or numeric data
  • Binary files are easily read by the computer but not humans
  • For Example

  • If we wanted to store an int value of 1234 in a file
  • We know an int is four bytes long
  • Can store our value as either 1234 or "1234"
  • How we store it determines what is actually written to the file
  • Byte 0 Byte 1 Byte 2 Byte 3
    00000000 00000000 00000100 11010010
    0 0 4 210
    49 50 51 52
    '1' '2' '3' '4'

10.1.5: Basic File I/O Classes

  • Most basic file I/O classes are:
    • FileInputStream for byte-based input from a file
    • FileOutputStream for byte-based output to a file
    • FileReader for character-based input from a file
    • FileWriter for character-based output to a file
  • Can create a file stream object for input of text:
  • FileReader fr = new FileReader("in.txt");
    
  • Statement both creates an input stream and opens the myfile.txt file for reading
  • If a file cannot be opened, then a FileNotFoundException is thrown
  • Can now use the fr variable to read from the file
  • fr.read()
    
  • Causes the next character in the file to be read
  • Similarly, we can open an output stream for text:
  • FileWriter fw = new FileWriter("out.txt");
    
  • When a file stream is created, a file with the given name is automatically created by the OS
  • If the file already exists, all the old data will be erased
  • To append data to an existing file, we open FileWriter with another parameter
  • FileWriter fw = new FileWriter("out.txt", true);
    
  • To write a character of data to the file, we can use:
  • fw.write('a');
    
  • Writes the character code for lowercase letter a to the file
  • Stream objects from the basic I/O classes are restricted to byte processing
  • Thus, they are usually enclosed in processing streams
  • Processing streams provide additional capabilities
  • Will discuss in later sections

Closing a Stream Object

  • Close a stream using the close method
  • fw.close();
    
  • All operating systems have a limit on the number of files that can be open
  • Thus, makes good sense to close them when no longer needed
  • All streams open at the end of a program are automatically closed
  • 10.1.6: Buffering

    • Every time a byte or sequence of bytes is written or read to a file, the OS must perform a series of operations
    • Buffering improves performance of I/O by reducing the number of calls to the OS
    • Copies each output to a region of memory called a buffer
    • Entire buffer output to disk at once
    • One long disk access takes less time than many smaller ones

    Java Buffering Classes

    • BufferedReader buffers text-file input
    • BufferedWriter buffers text-file output
    • BufferedInputStream buffers binary-file input
    • BufferedOutputStream buffers binary-file output
    • Creating a buffered stream requires another basic I/O stream object
    • Must first create another basic I/O object before we create a buffered stream
    • For example:
    • FileWriter fw = new FileWriter("myfile.txt")
      BufferedWriter buf = new BufferedWriter(fw);
      

    Exercise 10.1

    Take one minute to prepare an answer to the following question:

    1. Would it be appropriate to call a saved Java program a file? Why or why not?
    2. Which of the following is a valid way to open the file "scores.dat" to read data?
      1. FileWriter fw = new FileWriter();
      2. FileWriter fw = new FileWriter("scores.dat");
      3. FileReader fr = new FileReader();
      4. FileReader fr = new FileReader("scores.dat");

    10.2: Text File I/O

    Objectives

    At the end of the lesson the student will be able to:

    • Write text to files
    • Read text from files

    10.2.1: About Text File I/O

    • Binary files are more efficient for Computers
    • However text files are readable by humans
    • Often use text rather than binary files
    • Java allows both binary and text file I/O
    • In this section we discuss text file I/O

    Some Text I/O Stream Classes

    10.2.2: Text File Output

    • Writing text to a file involves using multiple classes
    • FileWriter provides the basic I/O capabilities and opens the file for writing
    • FileWriter fw = new FileWriter("hello.txt");
      
    • As mentioned earlier, I/O is faster if we buffer our output
    • BufferedWriter buf = new BufferedWriter(fw);
      
    • However, a BufferedWriter has minimal capabilities
    • Thus we need to connect our BufferedWriter to another more capable object
    • Class PrintWriter is a good choice
    • PrintWriter out = new PrintWriter(buf);
      
    • Now we can use print and println to write to the file
    • Putting this all together, we can create a simple text-file output class
    • import java.io.*;
      
      class WriteHello {
          public static void main(String[] args)
                  throws java.io.IOException {
              FileWriter fw = new FileWriter("hello.txt");
              BufferedWriter buf = new BufferedWriter(fw);
              PrintWriter out = new PrintWriter(buf);
              out.println("Hello, file system!");
              out.close();
          }
      }
      
    • What is the exception error I am making in this code?
    • PrintWriter has methods for all primitive types as well as Objects
    • With this capability, we can write all the different values to a text file
    • Each value is written in text format to the file
    • Thus we get "1234" and not 1234 stored in the file
    • import java.io.*;
      
      class WriteSamples {
          public static void main(String[] args)
                  throws java.io.IOException {
              FileWriter fw = new FileWriter("sample.txt");
              BufferedWriter buf = new BufferedWriter(fw);
              PrintWriter out = new PrintWriter(buf);
              out.println("This is a String");
              out.println(1234);
              out.println(1.234);
              for (int i = 0; i <= 10; i++)
                  out.print(i + ",");
              out.println();
              out.close();
          }
      }
      

    10.2.3: Text File Input

    • Reading text from a file also uses multiple classes
    • FileReader provides the basic I/O capabilities and opens the file for writing
    • FileReader fr = new FileReader("hello.txt");
      
    • As mentioned earlier, I/O is faster if we buffer our input
    • BufferedReader in = new BufferedReader(fr);
      
    • Now we use the readLine method of BufferedReader
    • Putting it all together we get:
    • import java.io.*;
      
      class ReadHello {
          public static void main(String[] args)
                  throws IOException {
              FileReader fr = new FileReader("hello.txt");
              BufferedReader in = new BufferedReader(fr);
              String msg = in.readLine();
              System.out.println(msg);
          }
      }
      
      
    • BufferedReader has no methods to read numbers directly
    • Nor is there an analogous class to PrintWriter
    • So we read numbers as Strings and then convert them
    • import java.io.*;
      
      class ReadSamples {
          public static void main(String[] args)
                  throws java.io.IOException {
              FileReader fr = new FileReader("sample.txt");
              BufferedReader in = new BufferedReader(fr);
              String st = in.readLine();
              System.out.println(st);
              int x = Integer.parseInt(in.readLine());
              System.out.println(x);
              double d = Double.parseDouble(in.readLine());
              System.out.println(d);
              String line = in.readLine();
              System.out.println(line);
              in.close();
          }
      }
      

    10.2.4: Testing for End of File

    • Several ways to test for the end of a file
    • For reading text files we can test for a special character
    • When method readLine tries to read beyond the end of a text file, it returns null
    • When method read tries to read beyond the end of a text file, it returns -1
    • Neither read nor readLine will throw an EOFException

    Exercise 10.2

    Take one minute to prepare an answer to the following question:

    1. What does the following snippet of code do?
    2. FileReader fr = new FileReader("myfile.txt");
      BufferedReader in = new BufferedReader(fr);
      
      int count = 0;
      String line = in.readLine();
      while (line != null) {
          count++;
          System.out.println(count + ": " + line);
          line = in.readLine();
      }
      

    10.3: Binary File I/O

    Objectives

    At the end of the lesson the student will be able to:

    • Write binary files
    • Read binary files

    10.3.1: About Binary File I/O

    • Binary file I/O uses the byte-oriented classes
    • Efficient for a computer to store information
    • Hard for a human to read

    Some Binary I/O Stream Classes

    Handling IOException

    • IOException cannot be ignored
    • Either handle it with a catch-block or defer it with a throws-clause
    • Open the file and write to it in a try-block and write a catch-block for this exception:
    • catch(IOException e) {
        System.out.println("Problem with output...");
      }
      

    10.3.2: Binary File Output

    • Opening a binary file for writing is similar to opening a text file for writing, though we use different classes
    • FileOutputStream provides the basic I/O capabilities and opens the file for output
    • FileOutputStream fos =
              new FileOutputStream("test.bin");
      
    • Alternatively, we could open our file for appending data
    • FileOutputStream fos =
              new FileOutputStream("test.bin", true);
      
    • We buffer the I/O for faster output using BufferedOutputStream
    • BufferedOutputStream bos =
              new BufferedOutputStream(fos);
      
    • However, a BufferedOutputStream has minimal capabilities
    • Thus we need to connect our BufferedOutputStream to a more capable object
    • Class DataOutputStream is a good choice
    • DataOutputStream out = new DataOutputStream(bos);
      
    • Now we can use writeBoolean, writeInt, writeDouble, etc. to write data to the file
    • Method for writing strings is called writeUTF
      • Writes a string using UTF-8 encoding
      • UTF-8 is a version of Unicode that uses one byte for ASCII characters
    • Putting all this together, we can create a simple binary-file output class
    • import java.io.*;
      
      class WriteBinData {
          public static void main(String[] args)
                  throws java.io.IOException {
              FileOutputStream fos =
                      new FileOutputStream("test.bin");
              BufferedOutputStream bos =
                      new BufferedOutputStream(fos);
              DataOutputStream out =
                      new DataOutputStream(bos);
              out.writeUTF("This is a String");
              out.writeBoolean(true);
              out.writeChar((int)'A');
              out.writeInt(1234);
              out.writeDouble(1.234);
              for (int i = 0; i <= 10; i++)
                  out.writeInt(i);
              out.close();
          }
      }
      

    10.3.3: Binary File Input

    • Opening a binary file for reading is similar to opening a binary file for writing, though we use input classes
    • FileInputStream provides the basic I/O capabilities and opens the file for input
    • FileInputStream fis =
              new FileInputStream("test.bin");
      
    • We buffer the I/O for faster input using BufferedInputStream
    • BufferedInputStream bis =
              new BufferedInputStream(fis);
      
    • However, a BufferedInputStream has minimal capabilities
    • Thus we need to connect BufferedInputStream to a more capable object
    • Class DataInputStream is a good choice
    • DataInputStream in = new DataInputStream(bis);
      
    • Now we can use readBoolean, readInt, readDouble, readUTF, etc. to read data from the file
    • Need to read data in the same order as it was written
    • import java.io.*;
      
      class ReadBinData {
          public static void main(String[] args)
                  throws java.io.IOException {
              FileInputStream fis =
                      new FileInputStream("test.bin");
              BufferedInputStream bis =
                      new BufferedInputStream(fis);
              DataInputStream in =
                      new DataInputStream(bis);
              System.out.println(in.readUTF());
              System.out.println(in.readBoolean());
              System.out.println(in.readChar());
              System.out.println(in.readInt());
              System.out.println(in.readDouble());
              for (int i = 0; i <= 10; i++)
                  System.out.print(in.readInt() + ",");
              System.out.println();
              in.close();
          }
      }
      

    10.3.4: Testing for End of an Input Stream

    • Common programming situation is to read data from an input file
    • Without knowing how much data the file contains
    • Need to check for the end of the file
    • Three common ways to test for the end of a file:
      • Test for a special character provided by the system that signals the end of the file
      • Put your own sentinel value at the end of the file and test for it
      • Catch an EOFException

      EOFException

    • Many (but not all) file-reading methods throw an EOFException
    • Occurs when they try to read beyond the end of the file
    • Many of the DataInputStream methods throw an EOFException
    • Can use EOFException in a loop that reads and processes data from a file
    • Loop terminates when an EOFException is thrown
    • Continues normally after the EOFException has been caught

    Exercise 10.3

    Take one minute to prepare an answer to the following question:

    1. What does the following snippet of code print?
    2. int x;
      try {
          try {
            while (true) {
                x = in.readInt();
                //do something with x
            }
          }
          catch(EOFException e) {
              System.out.println("End of reading file");
          }
          in.close();
          System.out.println("Continuing normally");
      } catch(IOException e) {
          // handle other problems
      }
      

    10.4: File Class

    Objectives

    At the end of the lesson the student will be able to:

    • Create and use File objects
    • Get information about files from the native file system
    • List directory contents

    10.4.1: Creating File Objects

    • File class represents a file on the native file system
    • Create a File object referring to a file
    • Then can query the object for information about that file

    Examples of Creating Files Objects

    • Can create a File object in the current directory
    • File myFile = new File("myfile.txt");
    • Can create a File object using an absolute pathname
    • Specifies the entire path and file name for the file
    • File myFile = new File("C:/docs/myfile.txt");
    • Can use a relative pathname to specify a file
    • Refers to a file starting from the current directory
    • File myFile = new File("docs/myfile.txt");
    • Can use a Universal Naming Convention to refer to a file
    • Starts with two slashes (//) followed by a hostname and pathname
    • File myFile = new File("//server/path/myfile.txt");
    • Can use two strings to specify a file
    • String pathname = "C:/docs";
      String filename = "myfile.txt";
      File myFile = new File(pathname, filename);
      
    • Can use a File object and a string to specify a file
    • File dir = "C:/docs";
      File myFile = new File(dir, "myfile.txt");
      
    • Note that forward slashes work on both UNIX and Windows systems
    • Always use forward slashes to make your code more portable

    Common Constructors for Class File

    Class Description
    File(String pathname) Creates a File object that refers to the specified pathname.
    File(String parent, String child) Creates a File object that refers to the pathname created by combining the parent and child pathnames.
    File(File parent, String child) Creates a File object that refers to the pathname created by combining the pathname of parent with the child pathname.

    10.4.2: Using File Objects

    • Can use File objects for many tasks
    • Can test some attributes of files or directories
    • Can get information about files
    • Can get lists of directory contents
    • Can create files and directories
    • Can delete files and directories

    Some Methods that Test a File

    Method Description
    canRead() Returns true if the pathname exists and can be read by the program.
    canWrite() Returns true if the pathname exists and a program can write to it.
    exists() Returns true if the pathname exists.
    isDirectory() Returns true if the pathname exists and refers to a directory.
    isFile() Returns true if the pathname exists and refers to a file.

    Some Methods that Return Information about a File

    Method Description
    getName() Returns the name of the file or directory as a String.
    getPath() Returns the name of the file or directory as a String.
    lastModified() Returns the time that the file was last modified as the number of milliseconds since January 1, 1970.
    length() Returns the length of the file as a long type.

    Some Methods that work with Directories

    Method Description
    list() If the object refers to a directory, returns an array of strings naming the files and directories.
    listFiles() If the object refers to a directory, returns an array of File objects for the files and directories.
    listRoots() A static method that returns an array of File objects representing the drives available to the current system.
    mkdir() Creates the directory named by the File pathname.

    Other Methods that work with File Objects

    Method Description
    createNewFile() Creates a new, empty file if a file with this name does not yet exist.
    delete() Deletes the file or directory referred to by the File object.
    setReadOnly() Makes the file read-only. If successful, returns true.

    10.4.3: Working with Files and Directories

    Getting Information About a File

    import java.io.*;
    
    public class FileInfo {
      public static void main(String[] args) throws IOException {
        File myFile = new File("myfile.txt");
        myFile.createNewFile();
        if (myFile.exists()) {
            System.out.println("Name:     " + myFile.getName());
            System.out.println("Path:     " + myFile.getPath());
            System.out.println("Writable: " + myFile.canWrite());
        } else
            System.out.println("The " + myFile.getName()
                    + " file doesn't exist.");
      }
    }

    Listing Directory Contents

    import java.io.*;
    
    public class DirList {
      public static void main(String[] args)
          throws IOException
      {
        File dir = new File("./"); //current directory
        if (dir.exists() && dir.isDirectory()) {
            System.out.println("Dir:     "
                + dir.getCanonicalPath());
            String[] files = dir.list();
            for (int i = 0; i < files.length; i++)
              System.out.println(files[i]);
        }
      }
    }

    Exercise 10.4

    Take one minute to prepare answers to the following questions:

    1. What is the purpose of the File class?
    2. What is an absolute pathname?
    3. What is a relative pathname?

    Wrap Up

    Home | WebCT | Announcements | Schedule | Expectations | Syllabus
    Help | FAQ's | HowTo's | Links

    Last Updated: November 16 2003 @19:27:48