File Input and Output



In the java.io package:



Use a Scanner object to read text from a file:
Scanner fileScan = new Scanner(new File("file name goes here"));



You may specify a relative or absolute path for the file, or just give the file's name if it is in the current directory:

Use forward slashes instead of backslashes, even on Windows machines, since Java will translate the file path correctly. Otherwise you must use the control sequence \\ for a backslash.






Dealing with Exceptions




A complication: A FileNotFoundException is thrown if the file we are attempting to read does not exist.



Recall: An exception is used to handle run-time errors in Java.



A checked exception is an exception that Java requires us to either:




Reading text from a file


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

public class FileExample
{
    public static void main(String[] args) throws FileNotFoundException
    {
          // create a Scanner object that reads from file "myFile.txt"
          Scanner fileIn = new Scanner(new File("myFile.txt"));

          // myFile.txt contains some integers - compute their sum
          int sum = 0;
          
// as long as there is another token and it's an int
          while(fileIn.hasNextInt())  
          {
                sum += fileIn.nextInt();
          }

          System.out.println("Sum = " + sum);
    }
}




Several methods allow us to check whether or not there is another token before we try to read a token. These methods do not advance the cursor past a token - they just peek ahead to see if there is another token.


Method
How it Works
hasNext()
True if there is another token, false otherwise
hasNextInt()
True if there is another token, and the next token is an int; false otherwise
hasNextDouble()
True if there's another token, and the next token is a double
hasNextLine()
True if there are more lines




Some More File Processing - an example


Write a program that prints all the integers in the file nums.txt. Some of the tokens may not be integers - ignore them.

Suppose nums.txt looks like this:
1    3
Abc
2 2 2       2

Your program's output should be:
1
3
2
2
2
2







Prompting the user for the file name

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

public class MoreFiles
{
    public static void main(String[] args) throws IOException
    {
          // ask the user for the filename
          Scanner scan  = new Scanner(System.in);
          System.out.print("What is the name of your file? ");
          String theFile = scan.nextLine();  // file may contain more than one word
          File fileIn = new File(theFile);

          // ask the user for another filename if the given file doesn't exist
          // exists() method in File class - checks whether file
          // exists and is readable

          while(!fileIn.exists()) 
          {
             System.out.print("Invalid file name! Try again: ");
             theFile = scan.nextLine();
             fileIn = new File(theFile);
          }

          // have a valid file name, create a Scanner object
          Scanner fileScan = new Scanner(fileIn);
         
          // process the file
          while(fileScan.hasNextLine())
          {
             ...
           }
    }
}




Methods from the File Class

Method What it does
exists() returns true if file exists, false otherwise
length() returns number of characters in file
canRead() returns true if file is readable
getAbsolutePath() returns full path to file (as a String)
getName() returns name of file (as a String), without a path
isDirectory() returns true if this File object represents a directory/folder
isFile() returns true if this File object represents a file (not a directory)
delete() deletes the file






File Output


In the java.io package:




import java.util.*;

import java.io.*;

public class FileOutput
{
       public static void main(String[] args) throws FileNotFoundException
       {
             PrintStream writeStream = new PrintStream(new File("output.txt"));
             writeStream.println("One");
             writeStream.println("Two");
             writeStream.println("Three");

             // close stream
             writeStream.close();
       }
}





Exercise:
Write a program that prompts the user for the name of two files. The program copies the text in the first file to the second file, over-writing the contents of the second file (if any).



More File Input

Example: Write a program that takes a file that contains integer quiz grades, and reports the change in adjacent quiz grades.

Sample input file: quizzes.dat
5 8  9 6  7 3 10

Output:
Quiz grade change: 3
Quiz grade change: 1
Quiz grade change: -3
Quiz grade change: 1
Quiz grade change: -4
Quiz grade change: 7




Line-Based Processing


Some files need to be processed line-by-line.

Example: Printing a file to the screen

getty.txt
Four score and seven years ago our fathers brought forth, upon this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.

Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived, and so dedicated, can long endure. We are met here on a great battlefield of that war. We have come to dedicate a portion of it as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this.

Suppose we want to display the contents of a speech or poem, and we want to preserve line breaks in the file. We can't do this, if we read the file token by token - we won't know where the line breaks should be.

import java.io.*;

import java.util.*;

public class Gettysburg

{

    public static void main(String[] args)

    {

        Scanner scan = new Scanner(System.in);

        System.out.print("File name? ");

        String fileName = scan.nextLine();

        // print file contents to screen, preserving line breaks

        printIt(fileName);

     }

    public static void printIt(String theFile) throws IOException

    {

        Scanner reader;

         File inputFile = new File(theFile);

         if(inputFile.exists())

         {    

                reader = new Scanner(inputFile);

                while(reader.hasNextLine())

                {

                    System.out.println(reader.nextLine());

                }

          }

}


Processing Line by Line

We can pass a String to a Scanner constructor:

To process a file line by line, we may want to create a new Scanner object to represent a single line:

Scanner reader = new Scanner(new File("<file name>"));

while(reader.hasNextLine())

{

    String line = reader.nextLine();

    Scanner lineScanner = new Scanner(line); 

    // process this line

}


Another File Processing Problem

Suppose we have a file like this:

quizGrades.dat

Elvis 4 10 6 7 9 9 2 4

Ken 2 4 1 6 7 4

Orlando 7 8 3 9 7 7 8 9

Lynn 8 7 9 6 9 10 8 9 9 7

Each line of the file contains a student's name, followed by their quiz grades in cs 312. 

Problem: Ask the user for the student's name, and then display the student's quiz grades to the screen.

Scanner reader = new Scanner(new File("quizGrades.dat"));

while(reader.hasNextLine())

{

    String line = reader.nextLine();

    Scanner lineScanner = new Scanner(line); 

    String name = lineScanner.next(); 

    // if this is the right student, print grades...

}

Exercise: Write a complete program to solve this problem.