9: Files and Streams

What We Will Cover


Continuations

Homework Questions?

Questions from last class?

Feedback on CodeLab

More About Arrays

9.1: Streams and File I/O

Objectives

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

  • List the types of files
  • Describe the purpose of a stream

9.1.1: About Program I/O

  • Program I/O = Program Input/Output
    • Input to and output from programs
  • Input can be from a keyboard, mouse, file or other input device
  • Output can be to a display screen, printer, file or other output device
  • 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 in a file, we need two items:
    • A file
    • A file stream object
  • We will look at files first

9.1.2: Files

File: a collection of data stored under a common name on a storage medium.

  • Files provide long-term storage of large amounts of data
  • Usually, you store files on non-volatile storage mediums
    • Magnetic disks
    • Optical disks
    • Flash storage, like USB storage devices
  • File are a single sequence of bytes
  • Byte 0 Byte 1 Byte 2 ... Byte n−1 End-of-file marker

  • The OS keeps track of the number of bytes in a file
    • Using either an end-of-file marker or counting the number of bytes
  • Files must have a name
    • Naming requirements depend on the underlying operating system (OS)
  • The OS organizes files into directories

9.1.3: 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
  • Programs group files into two broad categories: text and binary

Text Files

  • In text files, the bits represent printable characters
  • Files are usually stored as one byte per character (ASCII)
  • Each record (like a line) are often delimited by end-of-line characters
  • Individual fields within a record are often delimited by commas, tabs or other special characters
  • Source code is stored as a text file
  • You can read text files because each byte is translated by display devices into readable characters

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 by humans

For Example

  • If we wanted to store an int value of 1234 in a file
  • We know an int is four bytes long
  • We can store our value as either 1234 or "1234"
  • How we store it determines what is actually written to the file

Description Byte 0 Byte 1 Byte 2 Byte 3
1234 as binary bits 00000000 00000000 00000100 11010010
1234 as bytes 0 0 4 210
"1234" as char's '1' '2' '3' '4'
"1234" as ASCII codes 49 50 51 52

9.1.4: 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.)

  • A stream connects a program to an I/O object
  • 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

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

Basic File Streams

  • Since there are two types of files, there are streams to support each type
  • Use character streams to read and write text files
  • Use binary streams to read and write binary files

9.1.5: Layering Streams

  • Usually, any one stream does have not all the functionality you want
  • Instead, it is common to layer two or more streams

For Example

  • To write text to a file, we use a FileWriter object
  • FileWriter fw = new FileWriter("out.txt");
    
  • However, a FileWriter does not know how to write different types of data
  • That's why we combine the FileWriter with a PrintWriter
  • PrintWriter out = new PrintWriter(fw);
    
  • Now we can use the overloaded print() methods of a PrintWriter object to write various data types

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
  • A program copies each output to a block of memory called a buffer
  • The entire buffer is output to disk at once
  • One long disk access takes less time than many smaller ones

Adding a Buffered Layer

  • You use buffered stream classes to improve I/O performance
  • We can add a buffering layer to our previous stream example:
  • FileWriter fw = new FileWriter("myfile.txt");
    BufferedWriter buf = new BufferedWriter(fw);
    PrintWriter out = new PrintWriter(buf);
    
  • Another way to write the same functionality:
  • PrintWriter out = new PrintWriter(
                      new BufferedWriter(
                      new FileWriter("myfile.txt")));
    

9.1.6: Example of File I/O

  • As an example, let us write an application that reads and writes files
  • We read a file named infile.txt, which contains the following 3 values:
  • 10
    20
    30
    
  • We sum the numbers and write the sum to a second file named outfile.txt
  • What do you notice that is different about the following code?
import java.io.*;

class Sum3App {
    public static void main(String[] args)
            throws IOException {

        // Open the streams
        BufferedReader in = new BufferedReader(
                            new FileReader("infile.txt"));
        PrintWriter out = new PrintWriter(
                          new BufferedWriter(
                          new FileWriter("outfile.txt")));

        // Read and parse the data
        String str1 = in.readLine();
        double num1 = Double.parseDouble(str1);
        String str2 = in.readLine();
        double num2 = Double.parseDouble(str2);
        String str3 = in.readLine();
        double num3 = Double.parseDouble(str3);

        // Perform the computation
        double total = num1 + num2 + num3;

        // Output the results
        out.println("The sum of the first 3 numbers");
        out.print("in infile.txt is: " + total);

        // Close the streams
        in.close();
        out.close();

        System.out.println("Processing completed");
    }
}
  1. How does the program get its input?
  2. Where is the program output?

9.1.7: Procedure for File I/O

  1. Import the Java I/O library.
  2. import java.io.*;
    
  3. Open input and output streams as needed.
  4. BufferedReader in = new BufferedReader(
                        new FileReader("infile.txt"));
    PrintWriter out = new PrintWriter(
                      new BufferedWriter(
                      new FileWriter("outfile.txt")));
    
    
  5. Read or write data
  6. // Read and parse data
    String str1 = in.readLine();
    double num1 = Double.parseDouble(str1);
    
    // Output data
    out.println("The sum of the first 3 numbers");
    out.print("in infile.txt is: " + total);
    
  7. Close the streams when finished
  8. in.close();
    out.close();

9.1.8: Summary

  • Programs can read and write to files using streams
  • A stream is a one-way transmission path that either delivers data to a destination or that takes data from a source.
  • To read and write files, you use character streams
  • Buffers improve the performance of disc operations by reducing the number of device operations
  • To create a stream object with the desired functionality, you layer streams
  • The procedure for File I/O has four steps as shown above.

Exercise 9.1

Take 5 minutes to complete the following:

  1. Start a text file named exercise9.txt.
  2. Prepare the exercise header as described in the HowTo on submitting exercises
  3. Label this exercise: Exercise 9.1
  4. Submit all exercises for this lesson in one file unless instructed otherwise
  5. Complete the following and record the answers to any questions in exercise9.txt.

Specifications

  1. Start a program file named CopyOneApp.java with one main function. Make sure that the program compiles.
  2. Declare and open an input stream named in that reads from a file named infile.txt.
  3. Declare and open an output stream named out that writes to a file named outfile.txt.
  4. Add code to read one number from the input stream and save it to the output stream.
  5. Add code to close both of the streams.
  6. Compile and run your program.
  7. View the outfile.txt file to verify that one number was copied.
  8. Submit your completed program along with exercise9.txt.
  9. Q1: A program has read half of the lines in a file. What must the program do to reread the first line of the file a second time?

9.2: More I/O Topics

Objectives

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

  • Read multiple fields from one line
  • Check for end-of-file conditions
  • Code stream parameters in methods
  • Work with I/O exceptions

9.2.1: Appending to a File

  • The standard open operation for writing begins with an empty file
  • Even if the file exists you loose all the contents
  • To prevent loosing the information, you must open for appending to the file
  • new FileWriter("outfile.txt", true)
    
  • If the file doesn't exist then FileWriter creates it
  • If the file exists then FileWriter positions itself to append to the end
  • The second argument is a boolean value where true means append

9.2.2: Stream Parameters

  • Stream types can be parameters in methods
  • void readString(BufferedReader in) {
        String line = in.readLine();
        System.out.println(line);
    }
    
  • This allows us to open a file in one method and read data from it in other methods

For Example

  • For reading a file named data.txt containing with different types of data
  • This is a string
    c
    1234
    1.234
    
  • We create a series to methods to read each type of data
  • Making it easier to work with different data types in files
  • import java.io.*;
    
    class TextReaderApp {
        public static void main(String[] args)
                throws IOException {
            BufferedReader in = new BufferedReader(
                                new FileReader("data.txt"));
            String str = readString(in);
            System.out.println(str);
            char ch = readChar(in);
            System.out.println(ch);
            int num = readInt(in);
            System.out.println(num);
            double fp = readDouble(in);
            System.out.println(fp);
            in.close();
        }
    
        public static String readString(BufferedReader in)
                throws IOException {
            String str = in.readLine();
            return str;
        }
    
        public static char readChar(BufferedReader in)
                throws IOException {
            char ch = in.readLine().charAt(0);
            return ch;
        }
    
        public static int readInt(BufferedReader in)
                throws IOException {
            int x = Integer.parseInt(in.readLine());
            return x;
        }
    
        public static double readDouble(BufferedReader in)
                throws IOException {
            double d = Double.parseDouble(in.readLine());
            return d;
        }
    }
    

    9.2.3: Testing for End of File

    • Sometimes you do not know how many lines are in a file
    • To solve this, the typical approach is to use a loop to process the file
    • Then we need a sentinel value to end the loop
    • When method readLine() tries to read beyond the end of a file, it returns null
    • We can use this sentinel value to signal the end of a file

    For Example

    import java.io.*;
    import javax.swing.JOptionPane;
    
    class TextReaderApp2 {
        public static void main(String[] args)
                throws IOException {
            String fileName = JOptionPane.showInputDialog(
                            "Show which file?");
            File data = new File(fileName);
            BufferedReader in = new BufferedReader(
                                new FileReader(data));
    
            String line = in.readLine();
            while (line != null) {
                System.out.println(line);
                line = in.readLine();
            }
            in.close();
            System.exit(0);
        }
    }
    

    9.2.4: Handling I/O Exceptions

    • Recall that when handling user I/O exceptions, you can either throw them or code a try-catch statement
    • try {
        // One or more statements at least one of which
        //   should be capable of throwing an exception
      } catch (Exception e) {
        // Exception handling code
        // Can have many catch blocks
      }
      
    • Similarly, to handle I/O exceptions you need to throw them or code try-catch statements
    • There are three common exception classes you work with shown below
    • As when we handled user I/O exceptions, you can code your programs to avoid many of these exceptions

    Common I/O Exceptions

    Exception Description
    IOException General purpose I/O exception.
    EOFException Thrown when a program reads beyond the end of a file.
    FileNotFoundException Thrown when a program tries to open a file that does not exist.

    For Example

    import java.io.*;
    import javax.swing.JOptionPane;
    
    class TextReaderApp3 {
        public static void main(String[] args) {
            String fileName = JOptionPane.showInputDialog(
                            "Show which file?");
            showFile(fileName);
            System.exit(0);
        }
    
        public static void showFile(String fileName) {
            try {
                BufferedReader in = new BufferedReader(
                                    new FileReader(fileName));
                String line = in.readLine();
                while (line != null) {
                    System.out.println(line);
                    line = in.readLine();
                }
                in.close();
            } catch(FileNotFoundException fnfe) {
                System.out.println("No such file");
                return;
            } catch(IOException ioe) {
                System.out.println("Got an IOException.");
                System.exit(1);
            }
        }
    }
    

    9.2.5: Summary

    • The standard open operation for writing begins with an empty file
    • Even if the file exists you loose all the contents
    • To prevent loosing the information, you must open for appending to the file new
    • FileWriter("outfile.txt", true)
    • You can define streams types as method parameters
    • This allows you to pass one stream to many methods
    • public static double readDouble(BufferedReader in)
              throws IOException {
          double d = Double.parseDouble(in.readLine());
          return d;
      }
      
    • Sometimes you do not know how many lines are in a file
    • Since readLine() returns null when you reach the end of a file, you can use null as a sentinel value in a loop
    • String line = in.readLine();
      while (line != null) {
          System.out.println(line);
          line = in.readLine();
      }
      
    • Many Java I/O classes throw I/O exceptions that you need to handle
    • You either throw the exceptions or code try-catch statements

    Exercise 9.2

    1. Label this exercise: Exercise 9.2
    2. Submit all exercises for this lesson in one file unless instructed otherwise
    3. Complete the following and record the answers to any questions in exercise9.txt.

    Specifications

    In this exercise we write a program that prompts the user for the name of a file and then displays the file to the screen with line numbers before each line. For example:

    1: public class HelloWorld {
    2:      public static void main(String[] args) {
    3:         System.out.println("Hello, world!");
    4:     }
    5: }
    
    1. Copy the following code into a text editor and save the file as ShowFileApp.java.
    2. Stub out the method toScreen() that takes a single String parameter and returns nothing. Make sure your code compiles and runs.
    3. Add a method call to toScreen() in main(). Again, make sure your code compiles and runs.
    4. Define the function toScreen() so that it reads one line at a time from an input stream and displays each line it reads to the screen. Each line that gets displayed shows the number of the line.
    5. Submit your completed program with your other exercises for this lesson.
    import java.io.*;
    import javax.swing.JOptionPane;
    
    class ShowFileApp {
        public static void main(String[] args)
                throws IOException {
            String fileName = JOptionPane.showInputDialog(
                            "Show which file?");
            // Call method toScreen() here
    
            System.exit(0);
        }
    
        // Add new function toScreen() here
    }
    

    9.3: 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

    9.3.1: Creating File Objects

    • File class represents a file on the native file system
    • You 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.

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

    9.3.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]);
        }
      }
    }

    9.3.4: Avoiding FileNotFoundExceptions

    • A File object can be used instead of a file name when opening a stream
    • For example, to open an output stream:
    • File data = new File("data.txt");
      PrintWriter out = new PrintWriter(
                        new BufferedWriter(
                        new FileWriter(data)));
      
    • To open an input stream:
    • File data = new File("data.txt");
      BufferedReader in = new BufferedReader(
                          new FileReader(data));
      
    • You can use a File object to avoid a FileNotFoundException
    • Avoiding exceptions is often preferable
    • You should reserve exception handling for errors
    • Following example shows how to use File to avoid a FileNotFoundException
    • Any IOException that does occur is an exceptional problem
    • For Example

      try {
          File data = new File("data.txt");
          if (data.exists()) { // avoid FileNotFoundException
              BufferedReader in = new BufferedReader(
                                  new FileReader(data));
              String line = in.readLine();
              while (line != null) { // avoid EOFException
                  System.out.println(line);
                  line= in.readLine();
              }
              in.close();
          } else {
              System.out.println("File does not exist");
          }
      } catch (IOException ioe) {
          System.out.println("An IOException has occurred.");
          System.exit(1);
      }
      

      9.3.5: Summary

      • To identify a file you create a File object
      • You identify the file with either an absolute pathname or a relative pathname
      • To identify a file on a remote computer, you use the Universal Naming Convention
      • The File class provides many methods that you can use to:
        • Check whether a file or directory exists
        • Get information about a file
        • Create or delete files and directories
      • You can open file streams using a File object rather than a String name
      • Also, you can use a File object to avoid FileNotFoundExceptions

      Exercise 9.3

      1. Label this exercise: Exercise 9.3
      2. Submit all exercises for this lesson in one file unless instructed otherwise
      3. Complete the following and record the answers to any questions in exercise9.txt.

      Specifications

      1. Run the FileInfo program shown below.
      2. Add code to the program that displays the following information:
        • Length of the file
        • Time the files was last modified

        Q1: What is the name of the method that returns a file's length?

        Q2: What is the name of the method that returns when a file was last modified?

        Note: to display the timestamp in a more readable format, use the following code:

        import java.util.Date;
        ...
        Date ts = new Date(timestamp);
        System.out.println(ts);
        
      3. Submit your modified FileInfo program with the exercises for this lesson.
      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.");
        }
      }
      

      Wrap Up

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

      Last Updated: December 04 2004 @10:47:18